diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 14 | ||||
-rw-r--r-- | src/map/pc.c | 29 | ||||
-rw-r--r-- | src/map/pc.h | 4 | ||||
-rw-r--r-- | src/map/script.c | 6 | ||||
-rw-r--r-- | src/map/skill.c | 140 | ||||
-rw-r--r-- | src/map/status.c | 7 | ||||
-rw-r--r-- | src/map/status.h | 6 | ||||
-rw-r--r-- | src/map/unit.c | 12 |
8 files changed, 133 insertions, 85 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 4b762a559..17f12741b 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1759,7 +1759,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } } - if( sc && sc->count && sc->data[SC_DEFRATIOATK] && skill_num != PA_SACRIFICE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri ) + if( sc && sc->count && sc->data[SC_DEFRATIOATK] + && !is_boss(target) + && skill_num != PA_SACRIFICE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN + && !flag.cri ) flag.pdef = flag.pdef2 = sc->data[SC_DEFRATIOATK]->val1; // Occult Impact Effect if (!flag.idef || !flag.idef2) @@ -1780,6 +1783,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } } + if( sc && sc->count && sc->data[SC_IGNOREDEF] + && !is_boss(target) + && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS ) + { + i = cap_value(sc->data[SC_IGNOREDEF]->val1,1,100); + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } + if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { unsigned char target_count; //256 max targets should be a sane max diff --git a/src/map/pc.c b/src/map/pc.c index 0b658b90b..b1e558bc3 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1435,12 +1435,25 @@ int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short f return 1; } -void pc_autoscript_clear(struct s_autoscript *scripts, int max) +void pc_autoscript_clear(struct map_session_data *sd) { int i; - for (i = 0; i < max && scripts[i].script; i++) - script_free_code(scripts[i].script); - memset(scripts, 0, i*sizeof(struct s_autoscript)); + + if( sd->state.autocast ) + return; + + for (i = 0; i < MAX_PC_BONUS && sd->autoscript[i].script; i++) + script_free_code(sd->autoscript[i].script); + + for (i = 0; i < MAX_PC_BONUS && sd->autoscript2[i].script; i++) + script_free_code(sd->autoscript2[i].script); + + for (i = 0; i < MAX_PC_BONUS && sd->autoscript3[i].script; i++) + script_free_code(sd->autoscript3[i].script); + + memset(&sd->autoscript, 0, sizeof(struct s_autoscript)); + memset(&sd->autoscript2, 0, sizeof(struct s_autoscript)); + memset(&sd->autoscript3, 0, sizeof(struct s_autoscript)); } static int pc_bonus_autospell_del(struct s_autospell* spell, int max, short id, short lv, short rate, short card_id) @@ -3393,6 +3406,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 14532: // Battle_Manual25 case 14533: // Battle_Manual100 case 14545: // Battle_Manual300 + case 14592: // JOB_Battle_Manual if( sd->sc.data[SC_EXPBOOST] ) return 0; break; @@ -4603,10 +4617,11 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi if (sd->sc.data[SC_EXPBOOST]) bonus += sd->sc.data[SC_EXPBOOST]->val1; - if (!bonus) - return; - *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); + + if (sd->sc.data[SC_JEXPBOOST]) + bonus += sd->sc.data[SC_JEXPBOOST]->val1; + *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX); return; diff --git a/src/map/pc.h b/src/map/pc.h index ea8a13dec..21ae9a094 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -242,7 +242,7 @@ struct map_session_data { } itemhealrate[MAX_PC_BONUS]; // zeroed structures end here // manually zeroed structures start here. - struct s_autoscript autoscript[10], autoscript2[10], autoscript3[10]; //Auto script on attack, when attacked, on skill usage + struct s_autoscript autoscript[MAX_PC_BONUS], autoscript2[MAX_PC_BONUS], autoscript3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage // manually zeroed structures end here. // zeroed vars start here. int arrow_atk,arrow_ele,arrow_cri,arrow_hit; @@ -571,7 +571,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, int pc_updateweightstatus(struct map_session_data *sd); int pc_autoscript_add(struct s_autoscript *scripts, int max, short rate, short flag, short target, struct script_code *script, bool onskill); -void pc_autoscript_clear(struct s_autoscript *scripts, int max); +void pc_autoscript_clear(struct map_session_data *sd); int pc_bonus(struct map_session_data*,int,int); int pc_bonus2(struct map_session_data *sd,int,int,int); diff --git a/src/map/script.c b/src/map/script.c index a414de4ca..b5e00fe55 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -6594,7 +6594,7 @@ BUILDIN_FUNC(bonusautoscript) script = parse_script(str, "autoscript bonus", 0, 0); if( !script ) return 1; - if( !pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, target, script, false) ) + if( sd->state.autocast || !pc_autoscript_add(sd->autoscript, ARRAYLENGTH(sd->autoscript), rate, flag, target, script, false) ) { script_free_code(script); return 1; @@ -6622,7 +6622,7 @@ BUILDIN_FUNC(bonusautoscript2) script = parse_script(str, "autoscript2 bonus", 0, 0); if (!script) return 1; - if (!pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, target, script, false)) + if( sd->state.autocast || !pc_autoscript_add(sd->autoscript2, ARRAYLENGTH(sd->autoscript2), rate, flag, target, script, false) ) { script_free_code(script); return 1; @@ -6649,7 +6649,7 @@ BUILDIN_FUNC(bonusautoscript3) script = parse_script(str, "autoscript3 bonus", 0, 0); if( !script ) return 1; - if( !pc_autoscript_add(sd->autoscript3, ARRAYLENGTH(sd->autoscript3), rate, skill, target, script, true) ) + if( sd->state.autocast || !pc_autoscript_add(sd->autoscript3, ARRAYLENGTH(sd->autoscript3), rate, skill, target, script, true) ) { script_free_code(script); return 1; diff --git a/src/map/skill.c b/src/map/skill.c index fd9c4b674..6ca0eda3a 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1048,8 +1048,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int continue; // one or more trigger conditions were not fulfilled if( rand()%1000 > sd->autoscript[i].rate ) continue; + sd->state.autocast = 1; run_script(sd->autoscript[i].script,0,sd->autoscript[i].target?bl->id:src->id,0); - break; //Have only one script execute at a time. + sd->state.autocast = 0; } } @@ -1129,8 +1130,9 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, int s continue; if( rand()%1000 > sd->autoscript3[i].rate ) continue; + sd->state.autocast = 1; run_script(sd->autoscript3[i].script,0,sd->bl.id,0); - break; + sd->state.autocast = 0; } } @@ -1305,8 +1307,9 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * continue; // one or more trigger conditions were not fulfilled if( rand()%1000 > dstsd->autoscript2[i].rate ) continue; + dstsd->state.autocast = 1; run_script(dstsd->autoscript2[i].script,0,dstsd->autoscript2[i].target?src->id:bl->id,0); - break; //Have only one script execute at a time. + dstsd->state.autocast = 0; } } @@ -4073,10 +4076,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SG_FUSION: case GS_GATLINGFEVER: if( tsce ) - i = status_change_end(bl, type, -1); - else - i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,i); + { + clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, -1)); + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); break; case SL_KAITE: case SL_KAAHI: @@ -4109,35 +4114,40 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case TF_HIDING: case ST_CHASEWALK: if (tsce) - i = status_change_end(bl, type, -1); - else - i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,-1,i); //Hide skill-scream animation. + { + clif_skill_nodamage(src,bl,skillid,-1,status_change_end(bl, type, -1)); //Hide skill-scream animation. + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,-1,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); break; case TK_RUN: - if (tsce) - clif_skill_nodamage(src,bl,skillid,skilllv, - status_change_end(bl, type, -1)); - else { - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,0)); -// If the client receives a skill-use packet inmediately before -// a walkok packet, it will discard the walk packet! [Skotlex] -// So aegis has to resend the walk ok. - if (sd) clif_walkok(sd); - } + if (tsce) + { + clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, -1)); + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,0)); + if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] + clif_walkok(sd); // So aegis has to resend the walk ok. break; - case AS_CLOAKING: - if( !tsce ) - i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - else + if (tsce) + { i = status_change_end(bl, type, -1); - + if( i ) + clif_skill_nodamage(src,bl,skillid,-1,i); + else if( sd ) + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 0; + } + i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); if( i ) clif_skill_nodamage(src,bl,skillid,-1,i); - else - if( sd ) clif_skill_fail(sd,skillid,0,0); + else if( sd ) + clif_skill_fail(sd,skillid,0,0); break; case BD_ADAPTATION: @@ -4376,7 +4386,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; } - if( sd->state.autocast || sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu || skilllv > 2 ) + if( sd->state.autocast || sd->skillitem == AL_TELEPORT || (battle_config.skip_teleport_lv1_menu && skilllv == 1) || skilllv > 2 ) { if( skilllv == 1 ) pc_randomwarp(sd,3); @@ -4665,6 +4675,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: case SC_READYCOUNTER:case SC_DODGE: case SC_WARM: case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: + case SC_JEXPBOOST: continue; case SC_ASSUMPTIO: if( bl->type == BL_MOB ) @@ -5823,8 +5834,9 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data) if (ud->walktimer != -1 && ud->skillid != TK_RUN) unit_stop_walking(src,1); - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); - if ( battle_config.display_status_timers && sd ) + if( sd->skillitem == ud->skillid && skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] + if( battle_config.display_status_timers && sd ) clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv)); if( sd ) { @@ -5916,7 +5928,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data) } ud->skillid = ud->skilllv = ud->skilltarget = 0; - ud->canact_tick = tick; + if( sd->skillitem == ud->skillid && skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick; //You can't place a skill failed packet here because it would be //sent in ALL cases, even cases where skill_check_condition fails //which would lead to double 'skill failed' messages u.u [Skotlex] @@ -6029,10 +6042,13 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data) if(battle_config.skill_log && battle_config.skill_log&src->type) ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly); + if (ud->walktimer != -1) unit_stop_walking(src,1); - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); - if ( battle_config.display_status_timers && sd ) + + if( sd->skillitem == ud->skillid && skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); + if( battle_config.display_status_timers && sd ) clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv)); // if( sd ) // { @@ -6061,7 +6077,8 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data) return 1; } while(0); - ud->canact_tick = tick; + if( sd->skillitem == ud->skillid && skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick; ud->skillid = ud->skilllv = 0; if(sd) sd->skillitem = sd->skillitemlv = 0; @@ -6447,7 +6464,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk case PA_GOSPEL: if (sce && sce->val4 == BCT_SELF) + { status_change_end(src,SC_GOSPEL,-1); + return 0; + } else { sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); @@ -8136,6 +8156,16 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh return 1; } + switch( skill ) + { // Turn off check. + case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: + case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: + case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: + case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: + if( sc && sc->data[status_skill2sc(skill)] ) + return 1; + } + if( lv < 1 || lv > MAX_SKILL_LEVEL ) return 0; @@ -8153,23 +8183,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh return 0; } break; - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case TF_HIDING: - case AS_CLOAKING: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case CR_DEFENDER: - case ML_DEFENDER: - case ST_CHASEWALK: - case PA_GOSPEL: - case CR_SHRINK: - case TK_RUN: - case GS_GATLINGFEVER: - if(sc && sc->data[status_skill2sc(skill)]) - return 1; //Allow turning off. - break; - case AL_WARP: if(!battle_config.duel_allow_teleport && sd->duel_group) { // duel restriction [LuzZza] clif_displaymessage(sd->fd, "Duel: Can't use warp in duel."); @@ -8246,8 +8259,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh case TK_READYDOWN: case TK_READYSTORM: case TK_READYTURN: - if(sc && sc->data[status_skill2sc(skill)]) - return 1; //Enable disabling them regardless of who you are. case TK_JUMPKICK: if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ) {// Soul Linkers cannot use this skill @@ -8379,8 +8390,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh clif_skill_fail(sd,skill,0,0); return 0; case SG_FUSION: - if (sc && sc->data[SC_FUSION]) - return 1; if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) break; //Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex] @@ -8747,6 +8756,20 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short if( sd->skillitem == skill ) return req; // Item skills and Hocus-Pocus don't have requirements.[Inkfish] + sc = &sd->sc; + if( !sc->count ) + sc = NULL; + + switch( skill ) + { // Turn off check. + case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: + case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: + case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: + case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: + if( sc && sc->data[status_skill2sc(skill)] ) + return req; + } + j = skill_get_index(skill); if( j == 0 ) // invalid skill id return req; @@ -8754,9 +8777,6 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short return req; status = &sd->battle_status; - sc = &sd->sc; - if( !sc->count ) - sc = NULL; req.hp = skill_db[j].hp[lv-1]; hp_rate = skill_db[j].hp_rate[lv-1]; diff --git a/src/map/status.c b/src/map/status.c index 6015837f0..602978f18 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -475,6 +475,7 @@ void initChangeTables(void) //Cash Items StatusIconChangeTable[SC_EXPBOOST] = SI_EXPBOOST; StatusIconChangeTable[SC_ITEMBOOST] = SI_ITEMBOOST; + StatusIconChangeTable[SC_JEXPBOOST] = SI_CASH_PLUSONLYJOBEXP; StatusIconChangeTable[SC_LIFEINSURANCE] = SI_LIFEINSURANCE; StatusIconChangeTable[SC_BOSSMAPINFO] = SI_BOSSMAPINFO; StatusIconChangeTable[SC_DEF_RATE] = SI_DEF_RATE; @@ -1771,9 +1772,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) + sizeof(sd->itemhealrate) ); // clear autoscripts... - pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript)); - pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2)); - pc_autoscript_clear(sd->autoscript3, ARRAYLENGTH(sd->autoscript3)); + pc_autoscript_clear(sd); // vars zeroing. ints, shorts, chars. in that order. memset (&sd->arrow_atk, 0,sizeof(sd->arrow_atk) @@ -5864,6 +5863,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3*=val1; break; case SC_EXPBOOST: + case SC_JEXPBOOST: if (val1 < 0) val1 = 0; break; @@ -6232,6 +6232,7 @@ int status_change_clear(struct block_list* bl, int type) case SC_EXPBOOST: case SC_ITEMBOOST: case SC_HELLPOWER: + case SC_JEXPBOOST: continue; } diff --git a/src/map/status.h b/src/map/status.h index 6a3f89004..f79deca6f 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -310,8 +310,10 @@ typedef enum sc_type { SC_HPDRAIN, SC_SKILLATKBONUS, SC_ITEMSCRIPT, - SC_S_LIFEPOTION, + SC_S_LIFEPOTION, //290 SC_L_LIFEPOTION, + SC_JEXPBOOST, + SC_IGNOREDEF, SC_HELLPOWER, SC_MAX, //Automatically updated max, used in for's to check we are within bounds. @@ -632,7 +634,7 @@ enum si_type { // SI_REUSE_LIMIT_E = 309, // SI_REUSE_LIMIT_F = 310, // SI_INVINCIBLE = 311, -// SI_CASH_PLUSONLYJOBEXP = 312, + SI_CASH_PLUSONLYJOBEXP = 312, // SI_PARTYFLEE = 313, // SI_ANGEL_PROTECT = 314, }; diff --git a/src/map/unit.c b/src/map/unit.c index 9e7d813dc..21bf5c750 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1074,7 +1074,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh if( casttime <= 0 ) ud->state.skillcastcancel = 0; - ud->canact_tick = tick + casttime + 100; + if( sd->skillitem == skill_num && skill_get_cast(skill_num,skill_lv) ) + ud->canact_tick = tick + casttime + 100; if( sd ) { switch( skill_num ) @@ -1179,7 +1180,8 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh casttime = skill_castfix_sc(src, casttime); ud->state.skillcastcancel = castcancel&&casttime>0?1:0; - ud->canact_tick = tick + casttime + 100; + if( sd->skillitem == skill_num && skill_get_cast(skill_num,skill_lv) ) + ud->canact_tick = tick + casttime + 100; // if( sd ) // { // switch( skill_num ) @@ -1603,8 +1605,6 @@ int unit_skillcastcancel(struct block_list *bl,int type) } ud->canact_tick = tick; - if ( battle_config.display_status_timers && sd ) - clif_status_change(bl, SI_ACTIONDELAY, 0, 0); if(type&1 && sd) skill = sd->skillid_old; @@ -1954,9 +1954,7 @@ int unit_free(struct block_list *bl, int clrtype) pc_setrestartvalue(sd,2); pc_delinvincibletimer(sd); - pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript)); - pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2)); - pc_autoscript_clear(sd->autoscript3, ARRAYLENGTH(sd->autoscript3)); + pc_autoscript_clear(sd); if( sd->followtimer != -1 ) pc_stop_following(sd); |