Compare commits

...

5 Commits

Author SHA1 Message Date
Atemo
560f8afd9b Correction of the target for support skills for slave clone
* the slave clone now targets MST_MASTER, friendly clone targets MST_FRIEND
Fixed an issue where skills and conditions were duplicated
* ms for INF_SUPPORT_SKILL was modified and the same data was pushed twice
Fixed an issue where db->skill could exceed MAX_MOBSKILL+1
* the data was pushed once in INF_SUPPORT_SKILL then again later, without re-checking the size
2023-10-21 22:23:07 +02:00
aleos
c35a262f37 Clean up clone checks
* Default clone monster mode to MONSTER_TYPE_20. This resolves issues with clones receiving more modes than they should resulting in static behavior. See doc/mob_db_mode_list.txt for more types.
* Fixes atcommand clone not sending the correct flag value during the clone spawning process.
* Update documentation.
2023-10-19 09:26:02 -04:00
Aleos
957814679d
Merge branch 'master' into hotfix/issue7689_clone 2023-10-18 13:15:16 -04:00
Atemo
416a33720c Typo 2023-04-23 00:37:35 +02:00
Atemo
56d63d7eda Removed MD_NOCAST and MD_NORANDOMWALK from default clone mode
Added MD_NORANDOMWALK for slaveclone
2023-04-22 23:21:31 +02:00
4 changed files with 51 additions and 16 deletions

View File

@ -6836,9 +6836,10 @@ The mode can be specified to determine the behavior of the clone. Its
values are the same as the ones used for the mode field in the mob_db. The values are the same as the ones used for the mode field in the mob_db. The
default mode is aggressive, assists, can move, can attack. default mode is aggressive, assists, can move, can attack.
Flag can be either zero or one currently. If zero, the clone is a normal Flag options:
monster that'll target players, if one, it is considered a summoned monster, 0 - The clone is a normal monster that will target players (default).
and as such, it'll target other monsters. Defaults to zero. 1 - The clone is considered a summoned monster that will target other monsters.
2 - The clone is a slave and will support the master.
The duration specifies how long the clone will live before it is auto-removed. The duration specifies how long the clone will live before it is auto-removed.
Specified in seconds, defaults to no limit (zero). Specified in seconds, defaults to no limit (zero).

View File

@ -9086,7 +9086,7 @@ ACMD_FUNC(clone)
y = sd->bl.y; y = sd->bl.y;
} }
if((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, MD_NONE, flag?1:0, 0)) > 0) { if((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, MD_NONE, flag, 0)) > 0) {
clif_displaymessage(fd, msg_txt(sd,128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. clif_displaymessage(fd, msg_txt(sd,128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned.
return 0; return 0;
} }

View File

@ -4056,8 +4056,8 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
} }
if (mode > MD_NONE) //User provided mode. if (mode > MD_NONE) //User provided mode.
status->mode = mode; status->mode = mode;
else if (flag&1) //Friendly Character, remove looting. else if (flag&2)// Clone follows the creator
status->mode = static_cast<enum e_mode>(status->mode&(~MD_LOOTER)); status->mode = MONSTER_TYPE_24;
status->hp = status->max_hp; status->hp = status->max_hp;
status->sp = status->max_sp; status->sp = status->max_sp;
memcpy(&db->vd, &sd->vd, sizeof(struct view_data)); memcpy(&db->vd, &sd->vd, sizeof(struct view_data));
@ -4120,6 +4120,7 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
ms->msg_id = 0; ms->msg_id = 0;
inf = skill_get_inf(skill_id); inf = skill_get_inf(skill_id);
bool is_also_self = false;
if (inf&INF_ATTACK_SKILL) { if (inf&INF_ATTACK_SKILL) {
ms->target = MST_TARGET; ms->target = MST_TARGET;
ms->cond1 = MSC_ALWAYS; ms->cond1 = MSC_ALWAYS;
@ -4161,8 +4162,14 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
ms->delay = 5000; //With a minimum of 5 secs. ms->delay = 5000; //With a minimum of 5 secs.
} }
} else if (inf&INF_SUPPORT_SKILL) { } else if (inf&INF_SUPPORT_SKILL) {
ms->target = MST_FRIEND; if (master_id > 0 && (flag&2)) {
ms->cond1 = MSC_FRIENDHPLTMAXRATE; ms->target = MST_MASTER;
ms->cond1 = MSC_MASTERHPLTMAXRATE;
}
else {
ms->target = MST_FRIEND;
ms->cond1 = MSC_FRIENDHPLTMAXRATE;
}
ms->cond2 = 90; ms->cond2 = 90;
if (skill_id == AL_HEAL) if (skill_id == AL_HEAL)
ms->permillage = 5000; //Higher skill rate usage for heal. ms->permillage = 5000; //Higher skill rate usage for heal.
@ -4173,11 +4180,7 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
if (ms->delay < 2000) if (ms->delay < 2000)
ms->delay = 2000; //With a minimum of 2 secs. ms->delay = 2000; //With a minimum of 2 secs.
if (db->skill.size() < MAX_MOBSKILL) { //duplicate this so it also triggers on self. is_also_self = true;
ms->target = MST_SELF;
ms->cond1 = MSC_MYHPLTMAXRATE;
db->skill.push_back(ms);
}
} else { } else {
switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered. switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered.
case MO_TRIPLEATTACK: case MO_TRIPLEATTACK:
@ -4199,6 +4202,38 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
ms->delay = ms->delay*battle_config.mob_skill_delay/100; ms->delay = ms->delay*battle_config.mob_skill_delay/100;
db->skill.push_back(ms); db->skill.push_back(ms);
// Duplicate INF_SUPPORT_SKILL so it also triggers on self.
if (is_also_self && db->skill.size() < MAX_MOBSKILL) {
std::shared_ptr<s_mob_skill> ms = std::make_shared<s_mob_skill>();
ms->skill_id = skill_id;
ms->skill_lv = sd->status.skill[sk_idx].lv;
ms->state = MSS_ANY;
ms->permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5%
ms->emotion = -1;
ms->cancel = 0;
ms->casttime = skill_castfix(&sd->bl,skill_id, ms->skill_lv);
ms->delay = 5000+skill_delayfix(&sd->bl,skill_id, ms->skill_lv);
ms->msg_id = 0;
ms->target = MST_SELF;
ms->cond1 = MSC_MYHPLTMAXRATE;
ms->cond2 = 90;
if (skill_id == AL_HEAL)
ms->permillage = 5000; //Higher skill rate usage for heal.
else if (skill_id == ALL_RESURRECTION)
ms->cond2 = 1;
//Delay: Remove the stock 5 secs and add half of the support time.
ms->delay += -5000 +(skill_get_time(skill_id, ms->skill_lv) + skill_get_time2(skill_id, ms->skill_lv))/2;
if (ms->delay < 2000)
ms->delay = 2000; //With a minimum of 2 secs.
if (battle_config.mob_skill_rate!= 100)
ms->permillage = ms->permillage*battle_config.mob_skill_rate/100;
if (battle_config.mob_skill_delay != 100)
ms->delay = ms->delay*battle_config.mob_skill_delay/100;
db->skill.push_back(ms);
}
} }
} }

View File

@ -3665,9 +3665,8 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt)
base_status->speed = pSpeed; base_status->speed = pSpeed;
} }
// !FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] // Default clone mode (see mob_db_mode_list doc for more types)
// Give them all modes except these (useful for clones) base_status->mode = MONSTER_TYPE_20;
base_status->mode = static_cast<e_mode>(MD_MASK&~(MD_STATUSIMMUNE|MD_IGNOREMELEE|MD_IGNOREMAGIC|MD_IGNORERANGED|MD_IGNOREMISC|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK));
base_status->size = (sd->class_&JOBL_BABY) ? SZ_SMALL : (((sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER) ? battle_config.summoner_size : SZ_MEDIUM); base_status->size = (sd->class_&JOBL_BABY) ? SZ_SMALL : (((sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER) ? battle_config.summoner_size : SZ_MEDIUM);
if (battle_config.character_size && pc_isriding(sd)) { // [Lupus] if (battle_config.character_size && pc_isriding(sd)) { // [Lupus]