summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichieru <Michieru@users.noreply.github.com>2014-08-29 17:51:30 +0200
committerMichieru <Michieru@users.noreply.github.com>2014-08-29 17:51:30 +0200
commita06e53479131c25ce2343c431c688c57b3bfa2c0 (patch)
tree2c7e97912c83d029efc1e0461ccaa4ddd46bc50d /src
parentb9511727e6a754ad5a11d21d30df98451c2dd69c (diff)
downloadhercules-a06e53479131c25ce2343c431c688c57b3bfa2c0.tar.gz
hercules-a06e53479131c25ce2343c431c688c57b3bfa2c0.tar.bz2
hercules-a06e53479131c25ce2343c431c688c57b3bfa2c0.tar.xz
hercules-a06e53479131c25ce2343c431c688c57b3bfa2c0.zip
Fix status def calculation (bug:8306)
Updated script command 'sc_start' to allow for more variables and options rAthena 17326 (bug:8217) Fix Cart Tornado damage to official elemental crashing/memory error (thanks to Ind)
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c7
-rw-r--r--src/map/elemental.c3
-rw-r--r--src/map/script.c148
-rw-r--r--src/map/status.c48
4 files changed, 69 insertions, 137 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index edc7b38e5..b869ad47c 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1396,7 +1396,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
int i;
struct status_change *sc, *tsc;
struct map_session_data *sd, *tsd;
- struct status_data *st, *tst;
+ struct status_data *st, *tst, *bst;
nullpo_ret(src);
nullpo_ret(target);
@@ -1406,6 +1406,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
sc = status->get_sc(src);
tsc = status->get_sc(target);
st = status->get_status_data(src);
+ bst = status->get_base_status(src);
tst = status->get_status_data(target);
switch(attack_type){
@@ -2411,9 +2412,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case GN_CART_TORNADO:
{
- int strbonus = st->str; // FIXME Supposed to take only base STR, but current code wont allow that. So well just take STR for now. [Rytech]
- if ( strbonus > 130 ) // Max base stat limit on official is 130. So well allow no higher then 125 STR here. This limit prevents
- strbonus = 130; // the division from going any lower then 30 so the server wont divide by 0 if someone has 150 STR.
+ int strbonus = bst->str;
skillratio = 50 * skill_lv + (sd ? sd->cart_weight : battle_config.max_cart_weight) / 10 / (150 - strbonus) + 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5);
}
break;
diff --git a/src/map/elemental.c b/src/map/elemental.c
index caba02692..b594c8899 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -218,6 +218,9 @@ int elemental_delete(struct elemental_data *ed, int reply) {
sd->ed = NULL;
sd->status.ele_id = 0;
+ if( !ed->bl.prev )
+ return unit->free(&ed->bl, 0);
+
return unit->remove_map(&ed->bl, 0, ALC_MARK);
}
diff --git a/src/map/script.c b/src/map/script.c
index ecd12a3c1..2f0aa5831 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -10039,118 +10039,80 @@ BUILDIN(hideonnpc)
return true;
}
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start <effect_id>,<duration>,<val1>{,<unit_id>};
-BUILDIN(sc_start) {
+/* Starts a status effect on the target unit or on the attached player.
+ *
+ * sc_start <effect_id>,<duration>,<val1>{,<rate>,<flag>,{<unit_id>}};
+ * sc_start2 <effect_id>,<duration>,<val1>,<val2>{,<rate,<flag>,{<unit_id>}};
+ * sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<rate,<flag>,{<unit_id>}};
+ * <flag>
+ * &1: Cannot be avoided (it has to start)
+ * &2: Tick should not be reduced (by vit, luk, lv, etc)
+ * &4: sc_data loaded, no value has to be altered.
+ * &8: rate should not be reduced
+ */
+BUILDIN(sc_start)
+{
+ TBL_NPC * nd = map->id2nd(st->oid);
struct block_list* bl;
enum sc_type type;
- int tick;
- int val1;
- int val4 = 0;
+ int tick, val1, val2, val3, val4=0, rate, flag;
+ char start_type;
+ const char* command = script_getfuncname(st);
+
+ if(strstr(command, "4"))
+ start_type = 4;
+ else if(strstr(command, "2"))
+ start_type = 2;
+ else
+ start_type = 1;
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
- if( script_hasdata(st,5) )
- bl = map->id2bl(script_getnum(st,5));
- else
- bl = map->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status->sc2skill(type), val1);
- }
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = map->id2bl(script->potion_target);
- tick /= 2;// Thrown potions only last half.
- val4 = 1;// Mark that this was a thrown sc_effect
- }
-
- if( bl )
- status->change_start(NULL, bl, type, 10000, val1, 0, 0, val4, tick, 2);
-
- return true;
-}
+ //If from NPC we make default flag 1 to be unavoidable
+ if(nd && nd->bl.id == npc->fake_nd->bl.id)
+ flag = script_hasdata(st,5+start_type)?script_getnum(st,5+start_type):2;
+ else
+ flag = script_hasdata(st,5+start_type)?script_getnum(st,5+start_type):1;
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>};
-BUILDIN(sc_start2) {
- struct block_list* bl;
- enum sc_type type;
- int tick;
- int val1;
- int val4 = 0;
- int rate;
+ rate = script_hasdata(st,4+start_type)?min(script_getnum(st,4+start_type),10000):10000;
- type = (sc_type)script_getnum(st,2);
- tick = script_getnum(st,3);
- val1 = script_getnum(st,4);
- rate = script_getnum(st,5);
- if( script_hasdata(st,6) )
- bl = map->id2bl(script_getnum(st,6));
+ if(script_hasdata(st,(6+start_type)))
+ bl = map->id2bl(script_getnum(st,(6+start_type)));
else
bl = map->id2bl(st->rid);
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
+ if(tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0)
+ {// When there isn't a duration specified, try to get it from the skill_db
tick = skill->get_time(status->sc2skill(type), val1);
}
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
+ if(script->potion_flag == 1 && script->potion_target) { //skill.c set the flags before running the script, this is a potion-pitched effect.
bl = map->id2bl(script->potion_target);
tick /= 2;// Thrown potions only last half.
val4 = 1;// Mark that this was a thrown sc_effect
}
- if( bl )
- status->change_start(NULL, bl, type, rate, val1, 0, 0, val4, tick, 2);
-
- return true;
-}
-
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>};
-BUILDIN(sc_start4) {
- struct block_list* bl;
- enum sc_type type;
- int tick;
- int val1;
- int val2;
- int val3;
- int val4;
-
- type = (sc_type)script_getnum(st,2);
- tick = script_getnum(st,3);
- val1 = script_getnum(st,4);
- val2 = script_getnum(st,5);
- val3 = script_getnum(st,6);
- val4 = script_getnum(st,7);
- if( script_hasdata(st,8) )
- bl = map->id2bl(script_getnum(st,8));
- else
- bl = map->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status->sc2skill(type), val1);
- }
+ if(!bl)
+ return 0;
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = map->id2bl(script->potion_target);
- tick /= 2;// Thrown potions only last half.
+ switch(start_type) {
+ case 1:
+ status->change_start(bl, bl, type, rate, val1, 0, 0, val4, tick, flag);
+ break;
+ case 2:
+ val2 = script_getnum(st,5);
+ status->change_start(bl, bl, type, rate, val1, val2, 0, val4, tick, flag);
+ break;
+ case 4:
+ val2 = script_getnum(st,5);
+ val3 = script_getnum(st,6);
+ val4 = script_getnum(st,7);
+ status->change_start(bl, bl, type, rate, val1, val2, val3, val4, tick, flag);
+ break;
}
-
- if( bl )
- status->change_start(NULL, bl, type, 10000, val1, val2, val3, val4, tick, 2);
-
- return true;
+ return 0;
}
/// Ends one or all status effects on the target unit or on the attached player.
@@ -18926,9 +18888,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(disablenpc,"s"),
BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"),
- BUILDIN_DEF(sc_start,"iii?"),
- BUILDIN_DEF(sc_start2,"iiii?"),
- BUILDIN_DEF(sc_start4,"iiiiii?"),
+ BUILDIN_DEF(sc_start,"iii???"),
+ BUILDIN_DEF2(sc_start,"sc_start2","iiii???"),
+ BUILDIN_DEF2(sc_start,"sc_start4","iiiiii???"),
BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getstatus, "i?"),
BUILDIN_DEF(getscrate,"ii?"),
diff --git a/src/map/status.c b/src/map/status.c
index 25376b4b0..718deaefc 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -6294,9 +6294,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
int sc_def = 0, tick_def = -1; //-1 = use sc_def
//Linear resistance substracted from rate and tick after percentual resistance was applied
//Example: 25% -> sc_def2=2000 -> 5%; 2500ms -> tick_def2=2000 -> 500ms
- int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2 (pre-re only)
+ int sc_def2 = 0, tick_def2 = 0;
- struct status_data *st;
+ struct status_data *st, *bst;
struct status_change *sc;
struct map_session_data *sd;
@@ -6307,14 +6307,8 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
/// Returns the 'bl's level, capped to 'cap'
#define SCDEF_LVL_CAP(bl, cap) ( (bl) ? (status->get_lv(bl) > (cap) ? (cap) : status->get_lv(bl)) : 0 )
-/// Renewal level modifier.
-/// In renewal, returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
-/// In pre-renewal, returns zero.
-#ifdef RENEWAL
+/// returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) ( ( SCDEF_LVL_CAP((bl), (maxlv)) - SCDEF_LVL_CAP((src), (maxlv)) ) * (factor) )
-#else
-#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) 0
-#endif
//Status that are blocked by Golden Thief Bug card or Wand of Hermod
if (status->isimmune(bl))
@@ -6353,6 +6347,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sd = BL_CAST(BL_PC,bl);
st = status->get_status_data(bl);
+ bst = status_get_base_status(bl);
sc = status->get_sc(bl);
if( sc && !sc->count )
sc = NULL;
@@ -6394,7 +6389,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_DPOISON:
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
if (sd) {
//For players: 60000 - 450*vit - 100*luk
tick_def = st->vit*75;
@@ -6404,7 +6398,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick>>=1;
tick_def = (st->vit*200)/3;
}
-#endif
break;
case SC_SILENCE:
#ifdef RENEWAL
@@ -6428,14 +6421,12 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_SLEEP:
sc_def = st->int_*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_DEEP_SLEEP:
- sc_def = st->int_*50;
+ sc_def = bst->int_*50;
tick_def = 0; // Linear reduction instead
- tick_def2 = st->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
+ tick_def2 = bst->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
break;
case SC_DEC_AGI:
case SC_ADORAMUS:
@@ -6451,19 +6442,11 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sc_def = st->mdef*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
tick_def = 0; //No duration reduction
-#ifndef RENEWAL
- tick_def2 = 0; //No duration reduction
-#endif
break;
case SC_FREEZE:
sc_def = st->mdef*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
- tick_def = 0; //No duration reduction
-#ifdef RENEWAL
tick_def2 = status_get_luk(src) * -10; //Caster can increase final duration with luk
-#else
- tick_def2 = 0; //No duration reduction
-#endif
break;
case SC_CURSE:
// Special property: immunity when luk is zero
@@ -6477,24 +6460,17 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sc_def = st->luk*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(NULL, src, 99, 10); // Curse only has a level penalty and no resistance
tick_def = st->vit*100;
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_BLIND:
sc_def = (st->vit + st->int_)*50;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_CONFUSION:
sc_def = (st->str + st->int_)*50;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
- sc_def2 = -sc_def2; // Reversed sc_def2
tick_def2 = st->luk*10;
-#endif
break;
case SC_ANKLESNARE:
if(st->mode&MD_BOSS) // Lasts 5 times less on bosses
@@ -6506,7 +6482,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
if (sd) //Duration greatly reduced for players.
tick /= 15;
sc_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 99) * 20; // Linear Reduction of Rate
- tick_def2 = 0; //No duration reduction
break;
case SC_MARSHOFABYSS:
//5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second }
@@ -6548,10 +6523,10 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick_def2 = (st->vit + st->agi) * 70;
break;
case SC_COLD:
- tick_def2 = st->vit*100 + status->get_lv(bl)*20;
+ tick_def2 = bst->vit*100 + status->get_lv(bl)*20;
break;
case SC_VACUUM_EXTREME:
- tick_def2 = st->str*50;
+ tick_def2 = bst->str*50;
break;
case SC_MANDRAGORA:
sc_def = (st->vit + st->luk)*20;
@@ -6612,13 +6587,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
//When tick def not set, reduction is the same for both.
if(tick_def == -1)
tick_def = sc_def;
- if(tick_def2 == -1) {
-#ifdef RENEWAL
- tick_def2 = 0;
-#else
- tick_def2 = sc_def2;
-#endif
- }
//Natural resistance
if (!(flag&8)) {