From 8cd804f247a2d36ff8dc69d09a1004f5ec84197a Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 20 Apr 2006 23:24:20 +0000 Subject: - Added two columns to item_db: equip_script and unequip_script are scripts that are executed once when the corresponding item is equipped or unequipped respectively. - Removed bonuses bDamageWhenUnequip, bLoseSPWhenUnequip - Updated sql-files/item_db.sql with latest. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6204 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/itemdb.c | 116 +++++++++++++++++++++++++++++++++++++++++++++---- src/map/itemdb.h | 5 ++- src/map/map.h | 5 +-- src/map/pc.c | 129 +++++++++++++++++++------------------------------------ src/map/status.c | 2 - 5 files changed, 156 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/map/itemdb.c b/src/map/itemdb.c index cfb354383..5f5c21c16 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -854,13 +854,30 @@ static int itemdb_read_sqldb(void) if (sql_res) { // Parse each row in the query result into sql_row while ((sql_row = mysql_fetch_row(sql_res))) - { - /* +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+---------------+-----------------+--------------+-------------+------+------------+--------------+ - | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | - +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+---------------+-----------------+--------------+-------------+------+------------+--------------+ - | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | - +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+---------------+-----------------+--------------+-------------+------+------------+--------------+ */ - + { /*Table structure is: + 00 id + 01 name_english + 02 name_japanese + 03 type + 04 price_buy + 05 price_sell + 06 weight + 07 attack + 08 defence + 09 range + 10 slots + 11 equip_jobs + 12 equip_upper + 13 equip_genders + 14 equip_locations + 15 weapon_level + 16 equip_level + 17 refineable + 18 view + 19 script + 20 equip_script + 21 unequip_script + */ nameid = atoi(sql_row[0]); // If the identifier is not within the valid range, process the next row @@ -937,7 +954,29 @@ static int itemdb_read_sqldb(void) id->script = parse_script((unsigned char *) script, 0); } } else id->script = NULL; - + + if (id->equip_script) + aFree(id->equip_script); + if (sql_row[20] != NULL) { + if (sql_row[20][0] == '{') + id->equip_script = parse_script((unsigned char *) sql_row[20], 0); + else { + sprintf(script, "{%s}", sql_row[20]); + id->equip_script = parse_script((unsigned char *) script, 0); + } + } else id->equip_script = NULL; + + if (id->unequip_script) + aFree(id->unequip_script); + if (sql_row[21] != NULL) { + if (sql_row[21][0] == '{') + id->unequip_script = parse_script((unsigned char *) sql_row[21], 0); + else { + sprintf(script, "{%s}", sql_row[21]); + id->unequip_script = parse_script((unsigned char *) script, 0); + } + } else id->unequip_script = NULL; + // ---------- id->flag.available = 1; @@ -1077,9 +1116,54 @@ static int itemdb_readdb(void) aFree(id->script); id->script=NULL; } + if (id->equip_script) { + aFree(id->equip_script); + id->equip_script=NULL; + } + if (id->unequip_script) { + aFree(id->unequip_script); + id->unequip_script=NULL; + } + if((p=strchr(np,'{'))==NULL) continue; - id->script = parse_script((unsigned char *) p,lines); + + str[19] = p; //Script + np = strchr(p,'}'); + + while (np && np[1] && np[1] != ',') + np = strchr(np+1,'}'); //Jump close brackets until the next field is found. + if (!np || !np[1]) { + //Couldn't find the end of the script field. + id->script = parse_script((unsigned char *) str[19],lines); + continue; + } + np[1] = '\0'; //Set end of script + id->script = parse_script((unsigned char *) str[19],lines); + np+=2; //Skip to next field + + if(!np || (p=strchr(np,'{'))==NULL) + continue; + + str[20] = p; //Equip Script + np = strchr(p,'}'); + + while (np && np[1] && np[1] != ',') + np = strchr(np+1,'}'); //Jump close brackets until the next field is found. + if (!np || !np[1]) { + //Couldn't find the end of the script field. + id->equip_script = parse_script((unsigned char *) str[20],lines); + continue; + } + + np[1] = '\0'; //Set end of script + id->equip_script = parse_script((unsigned char *) str[20],lines); + np+=2; //Skip comma, to next field + + if(!np || (p=strchr(np,'{'))==NULL) + continue; + //Unequip script, last column. + id->unequip_script = parse_script((unsigned char *) p,lines); } fclose(fp); if (ln > 0) { @@ -1133,6 +1217,16 @@ static int itemdb_final_sub (DBKey key,void *data,va_list ap) aFree(id->script); id->script = NULL; } + if (id->equip_script) + { + aFree(id->equip_script); + id->equip_script = NULL; + } + if (id->unequip_script) + { + aFree(id->unequip_script); + id->unequip_script = NULL; + } // Whether to clear the item data (exception: do not clear the dummy item data if (flag && id != dummy_item) aFree(id); @@ -1153,6 +1247,10 @@ void do_final_itemdb(void) if (dummy_item) { if (dummy_item->script) aFree(dummy_item->script); + if (dummy_item->equip_script) + aFree(dummy_item->equip_script); + if (dummy_item->unequip_script) + aFree(dummy_item->unequip_script); aFree(dummy_item); dummy_item = NULL; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index f65b4b943..88741b3b6 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -34,7 +34,10 @@ struct item_data { // some script commands should be revised as well... unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2) unsigned class_upper : 3; //Specifies if the upper-type can equip it (1: normal, 2: upper, 3: baby) - unsigned char *script; // 攻撃,防御の属性設定もこの中で可能かな? + unsigned char *script; //Default script for everything. + unsigned char *equip_script; //Script executed once when equipping. + unsigned char *unequip_script;//Script executed once when unequipping. + struct { unsigned available : 1; unsigned value_notdc : 1; diff --git a/src/map/map.h b/src/map/map.h index 1c6c8214b..0a7ee5f90 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -603,8 +603,6 @@ struct map_session_data { int addeff3[SC_COMMON_MAX-SC_COMMON_MIN+1]; short addeff3_type[SC_COMMON_MAX-SC_COMMON_MIN+1]; short sp_gain_race[12]; - short unequip_losehp[11]; - short unequip_losesp[11]; // zeroed arrays end here. // zeroed structures start here struct s_autospell{ @@ -1116,11 +1114,12 @@ enum { SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017 SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020 SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025 - SP_SUBSIZE, SP_DAMAGE_WHEN_UNEQUIP, SP_ADD_ITEM_HEAL_RATE, SP_LOSESP_WHEN_UNEQUIP, SP_EXP_ADDRACE, // 2026-2030 + SP_SUBSIZE, SP_FREE, SP_ADD_ITEM_HEAL_RATE, SP_FREE2, SP_EXP_ADDRACE, // 2026-2030 SP_SP_GAIN_RACE, SP_SUBRACE2, SP_ADDEFF_WHENHIT_SHORT, // 2031-2033 SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037 SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040 SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE //2041 + //Before you add more here, notice that 2027&2029 are available. }; enum { diff --git a/src/map/pc.c b/src/map/pc.c index b9b532ea1..c7cf8b24f 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1184,7 +1184,6 @@ static int pc_bonus_item_drop(struct s_add_drop *drop, short *count, short id, s */ int pc_bonus(struct map_session_data *sd,int type,int val) { - int i; nullpo_retr(0, sd); switch(type){ @@ -1642,30 +1641,6 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(!sd->state.lr_flag) sd->hp_gain_value += val; break; - case SP_DAMAGE_WHEN_UNEQUIP: - if(!sd->state.lr_flag) { - for (i=0; i<11; i++) { - //I think this one is bugged, notice how it uses the item_db info rather - // than inventory equipped position index [Skotlex] -// if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) { - if(sd->status.inventory[current_equip_item_index].equip & equip_pos[i]) { - sd->unequip_losehp[i] += val; - break; - } - } - } - break; - case SP_LOSESP_WHEN_UNEQUIP: - if(!sd->state.lr_flag) { - for (i=0; i<11; i++) { -// if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) { - if(sd->status.inventory[current_equip_item_index].equip & equip_pos[i]) { - sd->unequip_losesp[i] += val; - break; - } - } - } - break; default: if(battle_config.error_log) ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); @@ -6231,7 +6206,10 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) sd->status.inventory[arrow].equip=32768; } status_calc_pc(sd,0); - + //OnEquip script [Skotlex] + if (sd->inventory_data[n] && sd->inventory_data[n]->equip_script) + run_script(sd->inventory_data[n]->equip_script,0,sd->bl.id,0); + if(sd->sc.count) { if (sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); @@ -6250,7 +6228,6 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos) */ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { - short hp = 0, sp = 0; nullpo_retr(0, sd); // -- moonsoul (if player is berserk then cannot unequip) @@ -6262,73 +6239,53 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) if(battle_config.battle_log) ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); - if(sd->status.inventory[n].equip){ - int i; - for(i=0;i<11;i++) { - if(sd->status.inventory[n].equip & equip_pos[i]) { - sd->equip_index[i] = -1; - if(sd->unequip_losehp[i] > 0) { - hp += sd->unequip_losehp[i]; - sd->unequip_losehp[i] = 0; - } - if(sd->unequip_losesp[i] > 0) { - sp += sd->unequip_losesp[i]; - sd->unequip_losesp[i] = 0; - } - } - } - if(sd->status.inventory[n].equip & 0x0002) { - sd->weapontype1 = 0; - sd->status.weapon = sd->weapontype2; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - if(sd->sc.data[SC_DANCING].timer!=-1) //When unequipping, stop dancing. [Skotlex] - skill_stop_dancing(&sd->bl); - } - if(sd->status.inventory[n].equip & 0x0020) { - sd->status.shield = sd->weapontype2 = 0; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); - } - if(sd->status.inventory[n].equip & 0x0001) { - sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - } - if(sd->status.inventory[n].equip & 0x0100) { - sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - } - if(sd->status.inventory[n].equip & 0x0200) { - sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - } - if(sd->status.inventory[n].equip & 0x0040) - clif_changelook(&sd->bl,LOOK_SHOES,0); - - clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); - sd->status.inventory[n].equip=0; - if(flag&1) - pc_checkallowskill(sd); - if(sd->weapontype1 == 0 && sd->weapontype2 == 0) - skill_enchant_elemental_end(&sd->bl,-1); //武器持ち誓えは無?件で?性付?解除 - } else { + if(!sd->status.inventory[n].equip){ //Nothing to unequip clif_unequipitemack(sd,n,0,0); + return 0; + } + + if(sd->status.inventory[n].equip & 0x0002) { + sd->weapontype1 = 0; + sd->status.weapon = sd->weapontype2; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + if(sd->sc.data[SC_DANCING].timer!=-1) //When unequipping, stop dancing. [Skotlex] + skill_stop_dancing(&sd->bl); + } + if(sd->status.inventory[n].equip & 0x0020) { + sd->status.shield = sd->weapontype2 = 0; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); } + if(sd->status.inventory[n].equip & 0x0001) { + sd->status.head_bottom = 0; + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + } + if(sd->status.inventory[n].equip & 0x0100) { + sd->status.head_top = 0; + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + } + if(sd->status.inventory[n].equip & 0x0200) { + sd->status.head_mid = 0; + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + } + if(sd->status.inventory[n].equip & 0x0040) + clif_changelook(&sd->bl,LOOK_SHOES,0); + clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); + sd->status.inventory[n].equip=0; + if(flag&1) + pc_checkallowskill(sd); + if(sd->weapontype1 == 0 && sd->weapontype2 == 0) + skill_enchant_elemental_end(&sd->bl,-1); //武器持ち誓えは無?件で?性付?解除 if(flag&1) { status_calc_pc(sd,0); if(sd->sc.count && sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele)) status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); } - - if (hp > 0 || sp > 0) { - if (hp > sd->status.hp) - hp = sd->status.hp; - if (sp > sd->status.sp) - sp = sd->status.sp; - pc_heal(sd, -hp, -sp); - } - + //OnUnEquip script [Skotlex] + if (sd->inventory_data[n] && sd->inventory_data[n]->unequip_script) + run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,0); return 0; } diff --git a/src/map/status.c b/src/map/status.c index d40830465..4eec25e6b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -701,8 +701,6 @@ int status_calc_pc(struct map_session_data* sd,int first) + sizeof(sd->addeff3) + sizeof(sd->addeff3_type) + sizeof(sd->sp_gain_race) - + sizeof(sd->unequip_losehp) - + sizeof(sd->unequip_losesp) ); -- cgit v1.2.3-70-g09d2