diff options
-rw-r--r-- | db/quest_db.conf | 80 | ||||
-rw-r--r-- | db/re/item_db.conf | 72 | ||||
-rw-r--r-- | db/re/map_zone_db.conf | 32 | ||||
-rw-r--r-- | npc/dev/test.txt | 7 | ||||
-rw-r--r-- | npc/instances/SealedShrine.txt | 13 | ||||
-rw-r--r-- | sql-files/item_db_re.sql | 34 | ||||
-rw-r--r-- | src/char/char.c | 315 | ||||
-rw-r--r-- | src/char/char.h | 2 | ||||
-rw-r--r-- | src/map/atcommand.c | 2 | ||||
-rw-r--r-- | src/map/battle.c | 17 | ||||
-rw-r--r-- | src/map/chrif.c | 37 | ||||
-rw-r--r-- | src/map/chrif.h | 2 | ||||
-rw-r--r-- | src/map/script.c | 9 | ||||
-rw-r--r-- | src/map/skill.c | 1 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc | 8 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc | 2 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.Hooks.inc | 54 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 12 |
18 files changed, 502 insertions, 197 deletions
diff --git a/db/quest_db.conf b/db/quest_db.conf index 7c2fcb591..55588dea2 100644 --- a/db/quest_db.conf +++ b/db/quest_db.conf @@ -3373,54 +3373,132 @@ quest_db: ( { Id: 5113 Name: "[Rest] Lord Knight" + Targets: ( + { + MobId: 1646 + Count: 1 + }, + ) }, { Id: 5114 Name: "[Rest] Paladin" + Targets: ( + { + MobId: 2235 + Count: 1 + }, + ) }, { Id: 5115 Name: "[Rest] High Priest" + Targets: ( + { + MobId: 1649 + Count: 1 + }, + ) }, { Id: 5116 Name: "[Rest] Champion" + Targets: ( + { + MobId: 2238 + Count: 1 + }, + ) }, { Id: 5117 Name: "[Rest] High Wizard" + Targets: ( + { + MobId: 1651 + Count: 1 + }, + ) }, { Id: 5118 Name: "[Rest] Professor" + Targets: ( + { + MobId: 2237 + Count: 1 + }, + ) }, { Id: 5119 Name: "[Rest] Whitesmith" + Targets: ( + { + MobId: 1648 + Count: 1 + }, + ) }, { Id: 5120 Name: "[Rest] Creator" + Targets: ( + { + MobId: 2236 + Count: 1 + }, + ) }, { Id: 5121 Name: "[Rest] Assassin Cross" + Targets: ( + { + MobId: 1647 + Count: 1 + }, + ) }, { Id: 5122 Name: "[Rest] Stalker" + Targets: ( + { + MobId: 2239 + Count: 1 + }, + ) }, { Id: 5123 Name: "[Rest] Sniper" + Targets: ( + { + MobId: 1650 + Count: 1 + }, + ) }, { Id: 5124 Name: "[Rest] Clown" + Targets: ( + { + MobId: 2240 + Count: 1 + }, + ) }, { Id: 5125 Name: "[Rest] Gypsy" + Targets: ( + { + MobId: 2241 + Count: 1 + }, + ) }, // Kagerou/Oboro Job Quest { @@ -5186,7 +5264,7 @@ quest_db: ( { Id: 7349 Name: "Vote" - TimeLimit: 1800 + TimeLimit: 7200 }, // Port Malaya { diff --git a/db/re/item_db.conf b/db/re/item_db.conf index c8d6c6ae0..5155db1f0 100644 --- a/db/re/item_db.conf +++ b/db/re/item_db.conf @@ -14126,6 +14126,7 @@ item_db: ( Script: <" bonus bInt,4; bonus bMdef,1; + bonus bMdef,getrefine(); bonus2 bSkillAtk,WZ_STORMGUST,getrefine(); if (getrefine() > 9) bonus2 bVariableCastrate,WZ_STORMGUST,-8; "> @@ -18620,6 +18621,7 @@ item_db: ( } if(getrefine()>8) { bonus bVariableCastrate,-20; + bonus bFixedCast,-200; } "> }, @@ -54151,6 +54153,9 @@ item_db: ( Loc: 256 Refine: false View: 615 + Script: <" + skill "SM_PROVOKE",3; + "> }, { Id: 5738 @@ -79964,7 +79969,7 @@ item_db: ( Id: 12402 AegisName: "29Fruit" Name: "29Truth" - Type: 2 + Type: 0 Buy: 0 Trade: { nodrop: true @@ -79975,6 +79980,7 @@ item_db: ( nomail: true noauction: true } + Script: <" percentheal 5,5; "> }, { Id: 12403 @@ -106847,7 +106853,7 @@ item_db: ( { Id: 16457 AegisName: "Tw_Nov_Scroll" - Name: "±?????????" + Name: "±???Â?Â?????" Type: 2 Buy: 20 Weight: 10 @@ -109443,7 +109449,7 @@ item_db: ( View: 11 Script: <" bonus2 bSkillAtk,RA_ARROWSTORM,(getrefine()*5); - bonus2 bSkillUseSP,RA_ARROWSTORM,(getrefine()*5); + bonus2 bSkillUseSP,RA_ARROWSTORM,(getrefine()*-5); if(readparam(bAgi)>=120) { bonus bAspd,1; } @@ -111051,11 +111057,11 @@ item_db: ( bonus bInt,2; bonus bHealPower,1; bonus bHealPower2,1; - if(getrefine() >= 6) { - bonus bHealPower,1; - } if(getrefine() >= 7) { - bonus bHealPower,1; + bonus bHealPower,5; + } + if(getrefine() >= 9) { + bonus bHealPower,3; } "> }, @@ -111353,13 +111359,9 @@ item_db: ( View: 761 Script: <" bonus bAtkRate,5; - if(getrefine() > 5 && getrefine() <= 12) { - bonus2 bAddRace,RC_DemiHuman,(getrefine() - 5); - bonus2 AddRaceTolerance,RC_DemiHuman,(getrefine() - 5); - } - if(getrefine() > 12) { - bonus2 bAddRace,RC_DemiHuman,7; - bonus2 AddRaceTolerance,RC_DemiHuman,7; + if(getrefine()>5) { + bonus2 bAddRace,RC_DemiHuman,(getrefine()-5); + bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); } "> }, @@ -111377,8 +111379,8 @@ item_db: ( bonus bMdef,5; bonus bMatkRate,5; if(getrefine()>5) { - bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); bonus2 bMagicAddRace,RC_DemiHuman,(getrefine()-5); + bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); } "> }, @@ -111437,7 +111439,12 @@ item_db: ( Loc: 256 EquipLv: 10 View: 766 - Script: <" bonus bMdef,3; "> + Script: <" + bonus bMdef,3; + autobonus "{ bonus bAtkEle,Ele_Dark; }",30,60000; + bonus2 bSubEle,Ele_Holy,-10; + bonus2 bSubRace,RC_Angel,-10; + "> }, { Id: 18606 @@ -112083,6 +112090,10 @@ item_db: ( Loc: 256 EquipLv: 80 View: 804 + Script: <" + bonus2 bHPDrainRate,10*(5+1*(getrefine()>7)+2*(getrefine()>8)+2*(getrefine()>9)),1+2*(getrefine()>5)+2*(getrefine()>7)+3*(getrefine()>9); + bonus2 bSPDrainRate,10*(5+1*(getrefine()>8)+2*(getrefine()>9)),1+(getrefine()>7)+2*(getrefine()>9); + "> }, { Id: 18653 @@ -112178,6 +112189,10 @@ item_db: ( Slots: 1 Loc: 768 View: 808 + Script: <" + bonus3 bAutoSpell,"SA_FLAMELAUNCHER",5,10; + bonus3 bAutoSpell,"AS_SONICBLOW",5,10; + "> }, { Id: 18660 @@ -112375,8 +112390,11 @@ item_db: ( Loc: 256 View: 817 Script: <" - bonus bMdef,1; - bonus bUnbreakableHelm,0; + bonus bMdef,7; + bonus bHealPower,5; + if(getrefine()>6) bonus bHealPower,5; + if(getrefine()>8) bonus bMatkRate,7; + if(getrefine()>11) bonus bMatkRate,5; "> }, { @@ -112391,7 +112409,11 @@ item_db: ( Job: 0xFFFFFFFE Loc: 256 View: 11 - Script: <" bonus bAgi,3; "> + Script: <" + bonus bAgi,3; + bonus bAspdRate,1; + bonus2 bSPLossRate,5,10000; + "> }, { Id: 18675 @@ -112745,6 +112767,10 @@ item_db: ( Loc: 256 Refine: false View: 844 + Script: <" + bonus2 bSubRace,RC_Fish,15; + bonus3 bAddMonsterDropItem,579,RC_Fish,5; + "> }, { Id: 18700 @@ -112868,6 +112894,9 @@ item_db: ( Loc: 256 EquipLv: 20 View: 853 + Script: <" + skill "AL_HEAL",3; + "> }, { Id: 18709 @@ -113365,7 +113394,10 @@ item_db: ( Slots: 1 Loc: 256 View: 888 - Script: <" bonus bStr,2; "> + Script: <" + bonus bStr,2; + bonus bMaxHP,100; + "> }, { Id: 18750 diff --git a/db/re/map_zone_db.conf b/db/re/map_zone_db.conf index 71616c4d4..eade47a40 100644 --- a/db/re/map_zone_db.conf +++ b/db/re/map_zone_db.conf @@ -181,6 +181,38 @@ zones: ( Assumptio_5_Scroll: true Greed_Scroll: true Pty_Assumptio_Scroll: true + Velum_Jamadhar: false + Velum_Scare: false + Velum_Buster: false + Velum_Guillotine: false + Velum_Spear: false + Velum_Glaive: false + Velum_Bible: false + Velum_Encyclopedia: false + Velum_Claw: false + Velum_Arc_Wand: false + Velum_Damascus: false + Velum_Stunner: false + Velum_Flail: false + Velum_Arbalest: false + Velum_CrossBow: false + Velum_Claymore: false + Velum_Katzbalger: false + Siege_Arrow_A: false + Siege_Arrow_S: false + Siege_Greave: false + Siege_Boots: false + Siege_Shoes: false + Siege_Manteau: false + Siege_Muffler: false + Siege_White_Potion: false + Siege_Blue_Potion: false + Woe_Violet_Potion: false + Woe_White_Potion: false + Woe_Blue_Potion: false + Siege_Plate: false + Siege_Suits: false + Siege_Robe: false } /* 5 second duration increase on GvG */ /* knockback disabled */ diff --git a/npc/dev/test.txt b/npc/dev/test.txt index 8e94d6ee7..9c2de9a55 100644 --- a/npc/dev/test.txt +++ b/npc/dev/test.txt @@ -611,6 +611,10 @@ function script HerculesSelfTestHelper { callsub(OnCheck, "Callsub (parent scope vars isolation)", .@x, 1); callsub(OnCheck, "Callsub (nested scopes)", callsub(OnTestNestedScope), 1); callsub(OnCheck, "Callsub (deeply nested scopes)", callsub(OnTestDeepNestedScope, 30, 0), 1); + .@x = 1; + .@y = callsub(OnSetReference, .@x); + callsub(OnCheck, "Callsub (setting references)", .@y, 2); + callsub(OnCheck, "Callsub (setting references)", .@x, 2); deletearray .@x; setarray .@x, 1, 2, 3, 4; callsub(OnCheck, "Callsub (array references)", callsub(OnTestArrayRefs, .@x), 4); @@ -750,6 +754,9 @@ OnCheckStr: callsub(OnReportError, .@msg$, .@val$, .@ref$); } return; +OnSetReference: + set getarg(0), getarg(0) + 1; + return getarg(0); } - script HerculesSelfTest -1,{ diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index 240bc1ac4..5bbe81d27 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -121,7 +121,7 @@ monk_test,309,146,3 script Friar Patrick#edq 4_M_OLDFRIAR,{ } else { for (.@i = 1; .@i <= 2; ++.@i) { - if( instance_attachmap("" + .@i + "@cata", .@instance) == "" ) + if( instance_attachmap(.@i + "@cata", .@instance) == "" ) break; } if( .@i < 2 ) { @@ -348,7 +348,7 @@ prt_monk,261,91,3 script Rust Blackhand#edq 4_M_DWARF,{ next; mes "[Rust Blackhand]"; mes "You'll never know how great this hat is until you get one. If you understood, go and get the ingredients."; - if (questprogress(3042)==1) + if (questprogress(3042)) erasequest 3042; setquest 3043; close; @@ -366,12 +366,12 @@ prt_monk,261,91,3 script Rust Blackhand#edq 4_M_DWARF,{ close; } } - else if (!.@new_maje && countitem(6004) == 0) { + else if (!.@new_maje && !countitem(6004)) { mes "[Rust Blackhand]"; mes "If you don't have business with me, go away! As you see, I make equipment for the Brothers at the monastery, not for adventurers like you. Do you understand?"; close; } - else if (.@new_maje == 2 && countitem(6004) > 0) { + else if (.@new_maje == 2 && countitem(6004)) { switch(select("About the Cursed Baphomet Doll:Stop talking.")) { case 1: mes "[Rust Blackhand]"; @@ -405,8 +405,9 @@ prt_monk,261,91,3 script Rust Blackhand#edq 4_M_DWARF,{ next; mes "[Rust Blackhand]"; mes "You'll never know how great this hat is until you get one. If you understood, go and get the ingredients."; - if (questprogress(3042)==1) + if (questprogress(3042)) erasequest 3042; + erasequest 3043; setquest 3043; close; case 2: @@ -423,7 +424,7 @@ prt_monk,261,91,3 script Rust Blackhand#edq 4_M_DWARF,{ close; } } - else if (.@new_maje == 2 && countitem(6004) == 0) { + else if (.@new_maje == 2 && !countitem(6004)) { mes "[Rust Blackhand]"; mes "Why are you hanging around here? If you don't want a ^4d4dffGigantic Magestic Goat^000000, go away."; close; diff --git a/sql-files/item_db_re.sql b/sql-files/item_db_re.sql index 4146d24ee..efa182cc7 100644 --- a/sql-files/item_db_re.sql +++ b/sql-files/item_db_re.sql @@ -968,7 +968,7 @@ REPLACE INTO `item_db` VALUES ('1642','Staff_Of_Darkness','Staff Of Darkness','4 REPLACE INTO `item_db` VALUES ('1643','Dead_Tree_Cane','Dead Tree CaneStaff','4','20','10','100','100','155','0','1','0','8487700','63','2','2','4','70',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,4; if (getrefine()>5) { bonus bInt,getrefine()-5; bonus bMaxHP,-200; bonus bMaxSP,-100; }','',''); REPLACE INTO `item_db` VALUES ('1644','Piercing_Staff_M','Staff of Piercing','4','20','10','500','80','145','0','1','0','99092','58','2','2','3','70',NULL,'1','10','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','bonus bInt,4; bonus bIgnoreMdefRate,10+getrefine();','',''); REPLACE INTO `item_db` VALUES ('1645','Lich_Bone_Wand_M','Lich\'s Bone Wand','4','20','10','800','60','170','0','1','2','99092','58','2','2','3','70',NULL,'1','10','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','bonus bInt,1; bonus bDex,1; bonus bAtkEle,Ele_Undead; bonus bMatkRate,20; bonus3 bAutoSpellWhenHit,NPC_WIDECURSE,5,10+getrefine(); if(getrefine()>=9) { bonus bMatkRate,3; bonus bMaxSP,300; }','',''); -REPLACE INTO `item_db` VALUES ('1646','La\'cryma_Stick','La\'cryma Stick','4','20','10','500','30','180','0','1','2','66052','58','2','2','3','50',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,4; bonus bMdef,1; bonus2 bSkillAtk,WZ_STORMGUST,getrefine(); if (getrefine() > 9) bonus2 bVariableCastrate,WZ_STORMGUST,-8;','',''); +REPLACE INTO `item_db` VALUES ('1646','La\'cryma_Stick','La\'cryma Stick','4','20','10','500','30','180','0','1','2','66052','58','2','2','3','50',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,4; bonus bMdef,1; bonus bMdef,getrefine(); bonus2 bSkillAtk,WZ_STORMGUST,getrefine(); if (getrefine() > 9) bonus2 bVariableCastrate,WZ_STORMGUST,-8;','',''); REPLACE INTO `item_db` VALUES ('1647','Croce_Staff','Croce Staff','4','20','10','500','30','175','0','1','1','33040','58','2','2','3','50',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAtkEle,Ele_Holy; bonus bInt,4; bonus4 bAutoSpellOnSkill,AL_HEAL,AL_BLESSING,max(getskilllv(AL_BLESSING),1),20;','',''); REPLACE INTO `item_db` VALUES ('1648','Staff_Of_Bordeaux','Staff Of Bordeaux','4','20','10','500','30','170','0','1','0','66052','58','2','2','4','50',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,2; bonus bDex,1; if(getskilllv(SA_DRAGONOLOGY) == 5) { bonus bUseSPrate,-15; bonus bInt,3; }','',''); REPLACE INTO `item_db` VALUES ('1649','Rafini_Staff','Laphine Staff','4','20','10','500','30','180','0','1','0','99072','56','2','2','3','100',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bFixedCastrate,-getrefine();','',''); @@ -1191,7 +1191,7 @@ REPLACE INTO `item_db` VALUES ('2012','Aqua_Staff2','Empowered Aqua Staff','4',' REPLACE INTO `item_db` VALUES ('2013','Crimson_Staff2','Empowered Crimson Staff','4','20','10','900','30','270','0','1','1','512','56','2','34','4','130',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAtkEle,Ele_Fire; bonus bInt,5; bonus2 bSkillAtk,MG_FIREBOLT,30; bonus2 bSkillAtk,MG_FIREBALL,30;','',''); REPLACE INTO `item_db` VALUES ('2014','Forest_Staff2','Empowered Forest Staff','4','20','10','900','30','270','0','1','1','512','56','2','34','4','130',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAtkEle,Ele_Earth; bonus bInt,5; bonus2 bSkillAtk,WZ_EARTHSPIKE,30; bonus2 bSkillAtk,WZ_HEAVENDRIVE,30;','',''); REPLACE INTO `item_db` VALUES ('2015','Upg_Staff','Upgrade Staff','4','20','10','1000','50','70','0','1','1','8487700','63','2','34','3','0',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMatk,(getrefine()*10); bonus bHealPower,getrefine(); if(BaseJob==Job_Wizard) bonus bMatk,30; else if(BaseJob==Job_Sage) bonus bMatk,20; if(BaseLevel>70) bonus bMatk,(((BaseLevel-70)/10)*10);','',''); -REPLACE INTO `item_db` VALUES ('2016','Velum_Arc_Wand','Vellum Arc Wand','4','20','10','800','110','220','0','1','0','8487700','63','2','34','4','95',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; bonus2 bMagicAddRace,RC_DemiHuman,25; bonus bIgnoreMdefRate,25; if(getrefine()>5) { bonus2 bMagicAddRace,RC_DemiHuman,15; } if(getrefine()>8) { bonus bVariableCastrate,-20; }','',''); +REPLACE INTO `item_db` VALUES ('2016','Velum_Arc_Wand','Vellum Arc Wand','4','20','10','800','110','220','0','1','0','8487700','63','2','34','4','95',NULL,'1','10','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; bonus2 bMagicAddRace,RC_DemiHuman,25; bonus bIgnoreMdefRate,25; if(getrefine()>5) { bonus2 bMagicAddRace,RC_DemiHuman,15; } if(getrefine()>8) { bonus bVariableCastrate,-20; bonus bFixedCast,-200; }','',''); REPLACE INTO `item_db` VALUES ('2017','Divine_Cross_','Divine Cross','4','20','10','1500','120','210','0','1','0','33024','63','2','34','4','70',NULL,'1','23','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; bonus bAtkEle,Ele_Holy; bonus bDex,4;','',''); REPLACE INTO `item_db` VALUES ('2018','Metal_Staff','Metal Staff','4','20','10','0','50','70','0','1','1','8487701','63','2','34','3','1',NULL,'1','23','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; if(BaseJob==Job_Wizard) bonus bMatk,15; else if(BaseJob==Job_Sage) bonus bMatk,10; bonus bMatk,(getrefine()*5); .@val = min(BaseLevel/10, 12); if (.@val > 2) bonus bMatk,((.@val-2)*5);','',''); REPLACE INTO `item_db` VALUES ('2023','Thanatos_Two-Handed_Staff','Thanatos Two-Handed Staff','4','20','10','1400','120','250','0','1','1','99092','56','2','34','4','120',NULL,'1','23','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,6; bonus bVit,6; bonus bLuk,-6; bonus2 bSPDrainRate,10,5; bonus2 bHPDrainRate,10,5; bonus2 bHPLossRate,100,10000; bonus bHealPower,18;','','heal -1000,0;'); @@ -3541,7 +3541,7 @@ REPLACE INTO `item_db` VALUES ('5733','E_Brooch_C','E Brooch C','5','1','0','0', REPLACE INTO `item_db` VALUES ('5734','E_Magestic_Goat_C','E Magestic Goat C','5','2','1','0','0','0','5','0','0','2147483646','63','2','256','0','0',NULL,'0','41','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,1;','',''); REPLACE INTO `item_db` VALUES ('5735','E_Ribbon_Green','E Ribbon Green','5','800','400','100','0','0','1','0','0','4294967295','63','0','256','0','0',NULL,'1','244','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,3;','',''); REPLACE INTO `item_db` VALUES ('5736','EF_Whisper_Mask','EF Whisper Mask','5','20','10','0','0','0','0','0','0','4294967295','63','2','769','0','0',NULL,'0','321','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableHelm,0; bonus bAgi,3; bonus2 bSubEle,Ele_Ghost,-10;','',''); -REPLACE INTO `item_db` VALUES ('5737','Cactus_Hat','Potted Muka Hat','5','20','10','300','0','0','1','0','0','4294967295','63','2','256','0','0',NULL,'0','615','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('5737','Cactus_Hat','Potted Muka Hat','5','20','10','300','0','0','1','0','0','4294967295','63','2','256','0','0',NULL,'0','615','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','skill \"SM_PROVOKE\",3;','',''); REPLACE INTO `item_db` VALUES ('5738','Snowman_Hat','Snowman Hat','5','20','10','300','0','0','4','0','1','4294967295','63','2','256','0','0',NULL,'1','616','0','0','0','73',NULL,'0',NULL,'0',NULL,'0','bonus bStr,1; bonus bInt,1; bonus bMdef,3; bonus2 bSubEle,Ele_Water,7; bonus2 bAddMonsterDropItem,530,100; bonus2 bAddMonsterDropItem,12354,300; if(getrefine()>7) { bonus5 bAutoSpellWhenHit,BA_FROSTJOKER,5,20,BF_WEAPON|BF_MAGIC,0; } else { bonus5 bAutoSpellWhenHit,BA_FROSTJOKER,1,20,BF_WEAPON|BF_MAGIC,0; }','',''); REPLACE INTO `item_db` VALUES ('5739','Sagittarius_Crown','Sagittarius Crown','5','20','10','300','0','0','3','0','0','4294967295','63','2','256','0','0',NULL,'1','617','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,2;','',''); REPLACE INTO `item_db` VALUES ('5740','Sagittarius_Diadem','Sagittarius Diadem','5','20','10','300','0','0','3','0','0','4294967295','63','2','256','0','0',NULL,'1','618','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,2; bonus bMdef,3;','',''); @@ -5838,7 +5838,7 @@ REPLACE INTO `item_db` VALUES ('12398','PCBang_Gift_Box','PCRoom Gift Box','2',' REPLACE INTO `item_db` VALUES ('12399','Castle_Treasure_Box','Castle Treasure Box','2','20','10','1000','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('12400','Water_Of_Blessing_','Water Of Blessing','2','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('12401','Rune_Kn_Test_Int','Rune Kn Test Int','2','0','0','0','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','sc_start SC_INCINT,300000,40;','',''); -REPLACE INTO `item_db` VALUES ('12402','29Fruit','29Truth','2','0','0','0','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('12402','29Fruit','29Truth','0','0','0','0','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','percentheal 5,5;','',''); REPLACE INTO `item_db` VALUES ('12403','Lucky_Egg_C2','RWC2011 Lucky Scroll','2','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('12404','Acti_Potion','Activation Potion','2','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('12405','Underripe_Yggseed','Unripe Seed Of Yggdrasil','2','20','10','50','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','475',NULL,'0',NULL,'0',NULL,'0','','',''); @@ -7752,7 +7752,7 @@ REPLACE INTO `item_db` VALUES ('16447','Scorpio_Crown_Box','Scorpio Crown Box',' REPLACE INTO `item_db` VALUES ('16448','Scorpio_Diadem_Box','Scorpio Diadem Box','18','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','getitem 5677,1;','',''); REPLACE INTO `item_db` VALUES ('16450','FScorpio_Diadem_Box','Scorpio Diadem Box','18','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','getitem 5677,1;','',''); REPLACE INTO `item_db` VALUES ('16456','My_Scroll1','Bride\'s Ribbon Scroll','2','20','10','0','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','packageitem();','',''); -REPLACE INTO `item_db` VALUES ('16457','Tw_Nov_Scroll','±?????????','2','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','packageitem();','',''); +REPLACE INTO `item_db` VALUES ('16457','Tw_Nov_Scroll','±???Â?Â?????','2','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','packageitem();','',''); REPLACE INTO `item_db` VALUES ('16461','Red_Wing_Hat_Box','Red Wing Hat Box','18','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','73',NULL,'0',NULL,'0',NULL,'0','getitem 5690,1;','',''); REPLACE INTO `item_db` VALUES ('16462','FRed_Wing_Hat_Box','Red Wing Hat Box','18','20','10','10','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','getitem 5690,1;','',''); REPLACE INTO `item_db` VALUES ('16466','My_Scroll2','Egg Of Light Scroll','2','20','10','0','0','0','0','0','0','4294967295','63','2','0','0','0',NULL,'0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','packageitem();','',''); @@ -8013,7 +8013,7 @@ REPLACE INTO `item_db` VALUES ('18106','P_Bow3','Eden Group Bow3','4','0','0','0 REPLACE INTO `item_db` VALUES ('18107','Malang_Snow_Crab','Malang Snow Crab','4','0','0','0','120','0','0','5','0','657480','63','2','34','1','50',NULL,'0','11','0','0','0','507',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; bonus bLuk,3; bonus bCritAtkRate,50; if(BaseLevel>99) { bonus bLongAtkRate,10; }','',''); REPLACE INTO `item_db` VALUES ('18108','Brindle_Eel','Brindle Eel','4','0','0','0','180','0','0','5','0','526336','63','2','34','1','50',NULL,'0','11','0','0','0','507',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableWeapon,0; bonus bAgi,3; autobonus \"{ bonus bAspd,2; }\",10,7000,BF_WEAPON,\"{ specialeffect2 EF_HASTEUP; }\"; if(BaseLevel>99) { bonus bLongAtkRate,10; }','',''); REPLACE INTO `item_db` VALUES ('18109','Catapult','Catapult','4','56000','28000','1100','150','0','0','5','2','131072','56','2','34','4','100',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bSkillAtk,SC_TRIANGLESHOT,(getrefine()*2); bonus2 bSkillUseSP,SC_TRIANGLESHOT,(getrefine()*2);','',''); -REPLACE INTO `item_db` VALUES ('18110','Big_CrossBow','Big CrossBow','4','56000','28000','900','160','0','0','5','2','2048','56','2','34','4','110',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bSkillAtk,RA_ARROWSTORM,(getrefine()*5); bonus2 bSkillUseSP,RA_ARROWSTORM,(getrefine()*5); if(readparam(bAgi)>=120) { bonus bAspd,1; }','',''); +REPLACE INTO `item_db` VALUES ('18110','Big_CrossBow','Big CrossBow','4','56000','28000','900','160','0','0','5','2','2048','56','2','34','4','110',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bSkillAtk,RA_ARROWSTORM,(getrefine()*5); bonus2 bSkillUseSP,RA_ARROWSTORM,(getrefine()*-5); if(readparam(bAgi)>=120) { bonus bAspd,1; }','',''); REPLACE INTO `item_db` VALUES ('18111','Creeper_Bow','Creeper Bow','4','56000','28000','1500','150','0','0','5','2','526336','56','2','34','3','120',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,1; bonus3 bAutoSpell,PF_SPIDERWEB,1,200;','',''); REPLACE INTO `item_db` VALUES ('18112','Upg_Bow','Upgrade Bow','4','20','10','600','60','0','0','5','1','526344','63','2','34','3','0',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bBaseAtk,(getrefine()*7); bonus bLongAtkRate,(getrefine()*2); if(BaseJob==Job_Hunter) bonus bBaseAtk,20; if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);','',''); REPLACE INTO `item_db` VALUES ('18113','Velum_Arbalest','Vellum Arbalest','4','20','10','1100','50','0','0','5','0','657480','63','2','34','4','95',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus3 bSPVanishRate,10000,4,BF_NORMAL; bonus bAspd,-5;','',''); @@ -8110,7 +8110,7 @@ REPLACE INTO `item_db` VALUES ('18576','YinYang_Earring','Yin Yang Earrings','5' REPLACE INTO `item_db` VALUES ('18577','24_Bolt','Screw Stuck Head','5','20','10','200','0','0','0','0','0','4294967295','63','2','512','0','10',NULL,'0','696','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18578','Helm_Of_Valor','Helm Of Valor','5','0','0','0','0','0','4','0','0','4294967295','63','2','256','0','0',NULL,'0','258','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18579','9th_Anni_Hat','kRO 9 Anniversary Hat','5','0','0','90','0','0','0','0','0','4294967295','63','2','256','0','0',NULL,'1','745','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableHelm,0; bonus bMdef,9;','',''); -REPLACE INTO `item_db` VALUES ('18580','Yggdrasil_Crown','Yggdrasil Crown','5','20','10','200','0','0','3','0','1','4294967295','63','1','256','0','0',NULL,'1','746','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bVit,2; bonus bInt,2; bonus bHealPower,1; bonus bHealPower2,1; if(getrefine() >= 6) { bonus bHealPower,1; } if(getrefine() >= 7) { bonus bHealPower,1; }','',''); +REPLACE INTO `item_db` VALUES ('18580','Yggdrasil_Crown','Yggdrasil Crown','5','20','10','200','0','0','3','0','1','4294967295','63','1','256','0','0',NULL,'1','746','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bVit,2; bonus bInt,2; bonus bHealPower,1; bonus bHealPower2,1; if(getrefine() >= 7) { bonus bHealPower,5; } if(getrefine() >= 9) { bonus bHealPower,3; }','',''); REPLACE INTO `item_db` VALUES ('18581','Red_Tiger_Mask','Red Tiger Mask','5','20','10','400','0','0','2','0','0','4294967295','63','2','768','0','50',NULL,'0','747','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,3;','',''); REPLACE INTO `item_db` VALUES ('18582','Blue_Tiger_Mask','Blue Tiger Mask','5','20','10','400','0','0','2','0','0','4294967295','63','2','768','0','50',NULL,'0','748','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,3;','',''); REPLACE INTO `item_db` VALUES ('18583','Navy_Drooping_Kitty','Navy Drooping Kitty','5','250000','125000','500','0','0','3','0','0','2147483646','63','2','256','0','0',NULL,'1','749','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,15;','',''); @@ -8130,12 +8130,12 @@ REPLACE INTO `item_db` VALUES ('18596','Sprout_Hat','Sprout Hat','5','45000','22 REPLACE INTO `item_db` VALUES ('18597','Mercury_Helm','Mercury Riser','5','45000','22500','400','0','0','10','0','1','4294967295','63','2','256','0','70',NULL,'1','759','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAspdRate,3; bonus bCritical,3; if(getrefine() >= 7) { bonus bAspdRate,2; bonus bCritical,2; } if(getrefine() >= 9) { bonus bAspdRate,2; bonus bCritical,2; }','',''); REPLACE INTO `item_db` VALUES ('18598','Mini_Tree_J','Holy xmas Tree','5','20','10','50','0','0','0','0','1','4294967295','63','2','256','0','0',NULL,'0','727','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,20;','',''); REPLACE INTO `item_db` VALUES ('18599','Black_Devil_Mask','Black Devil\'s Mask','5','20','10','100','0','0','0','0','0','4294967295','63','2','512','0','0',NULL,'0','760','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAllStats,2;','',''); -REPLACE INTO `item_db` VALUES ('18600','Cat_Ears_Beret','Cat Ear Beret','5','20','10','300','0','0','5','0','1','4294967295','63','2','256','0','0',NULL,'1','761','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAtkRate,5; if(getrefine() > 5 && getrefine() <= 12) { bonus2 bAddRace,RC_DemiHuman,(getrefine() - 5); bonus2 AddRaceTolerance,RC_DemiHuman,(getrefine() - 5); } if(getrefine() > 12) { bonus2 bAddRace,RC_DemiHuman,7; bonus2 AddRaceTolerance,RC_DemiHuman,7; }','',''); -REPLACE INTO `item_db` VALUES ('18601','Red_Bread_Hat','Red Pom Band','5','20','10','300','0','0','0','0','1','4294967295','63','2','256','0','0',NULL,'1','762','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,5; bonus bMatkRate,5; if(getrefine()>5) { bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); bonus2 bMagicAddRace,RC_DemiHuman,(getrefine()-5); }','',''); +REPLACE INTO `item_db` VALUES ('18600','Cat_Ears_Beret','Cat Ear Beret','5','20','10','300','0','0','5','0','1','4294967295','63','2','256','0','0',NULL,'1','761','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAtkRate,5; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,(getrefine()-5); bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); }','',''); +REPLACE INTO `item_db` VALUES ('18601','Red_Bread_Hat','Red Pom Band','5','20','10','300','0','0','0','0','1','4294967295','63','2','256','0','0',NULL,'1','762','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,5; bonus bMatkRate,5; if(getrefine()>5) { bonus2 bMagicAddRace,RC_DemiHuman,(getrefine()-5); bonus2 bAddRaceTolerance,RC_DemiHuman,(getrefine()-5); }','',''); REPLACE INTO `item_db` VALUES ('18602','Watermelon_Slice','Watermelon Bite','5','20','10','100','0','0','0','0','0','4294967295','63','2','1','0','30',NULL,'0','763','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableHelm,0; bonus bMdef,4; bonus2 bAddEle,Ele_Fire,4;','',''); REPLACE INTO `item_db` VALUES ('18603','Black_Devil_Mask_','Black Devil\'s Mask','5','20','10','100','0','0','0','0','1','4294967295','63','2','512','0','0',NULL,'0','760','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAllStats,1;','',''); REPLACE INTO `item_db` VALUES ('18604','Falcon_Mask','Falcon Mask','5','10','5','30','0','0','0','0','1','4294967295','63','2','513','0','50',NULL,'0','782','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); -REPLACE INTO `item_db` VALUES ('18605','Dark_Age','Dark Age','5','20','10','200','0','0','3','0','1','4294967295','63','2','256','0','10',NULL,'1','766','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,3;','',''); +REPLACE INTO `item_db` VALUES ('18605','Dark_Age','Dark Age','5','20','10','200','0','0','3','0','1','4294967295','63','2','256','0','10',NULL,'1','766','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,3; autobonus \"{ bonus bAtkEle,Ele_Dark; }\",30,60000; bonus2 bSubEle,Ele_Holy,-10; bonus2 bSubRace,RC_Angel,-10;','',''); REPLACE INTO `item_db` VALUES ('18606','Tear_Drop','Tear drop','5','20','10','100','0','0','1','0','0','4294967295','63','2','513','0','30',NULL,'0','767','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18607','Blush_','Blush','5','20','10','100','0','0','0','0','1','4294967295','63','2','512','0','0',NULL,'0','125','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18608','Pair_Of_Red_Ribbon2','Small Ribbons','5','20','10','100','0','0','2','0','1','4294967295','63','2','512','0','45',NULL,'0','169','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); @@ -8182,14 +8182,14 @@ REPLACE INTO `item_db` VALUES ('18648','Tongue_Charm','Tongue Charm','5','20','1 REPLACE INTO `item_db` VALUES ('18649','Lude_Mask','Lude Mask','5','10','5','100','0','0','1','0','0','4294967295','63','2','513','0','0',NULL,'1','802','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18650','RWC_Shouting_Mouth','RWC Shouting Mouth','5','20','10','50','0','0','0','0','0','4294967295','63','2','1','0','0',NULL,'0','194','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18651','Ignis_Cap','Ignis Cap','5','20','10','800','0','0','8','0','1','4294967295','63','2','256','0','40',NULL,'1','803','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); -REPLACE INTO `item_db` VALUES ('18652','Vanargandr_Helm','Vanargand Helm','5','20','10','1500','0','0','10','0','1','4294967295','63','2','256','0','80',NULL,'1','804','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('18652','Vanargandr_Helm','Vanargand Helm','5','20','10','1500','0','0','10','0','1','4294967295','63','2','256','0','80',NULL,'1','804','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bHPDrainRate,10*(5+1*(getrefine()>7)+2*(getrefine()>8)+2*(getrefine()>9)),1+2*(getrefine()>5)+2*(getrefine()>7)+3*(getrefine()>9); bonus2 bSPDrainRate,10*(5+1*(getrefine()>8)+2*(getrefine()>9)),1+(getrefine()>7)+2*(getrefine()>9);','',''); REPLACE INTO `item_db` VALUES ('18653','Deviruchi_Headphone','Headphones Debiruchi','5','20','10','200','0','0','8','0','1','4294967295','63','2','256','0','30',NULL,'1','805','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,4; bonus bAgi,2;','',''); REPLACE INTO `item_db` VALUES ('18654','SS_Bandana','SS Bandana','5','1000','500','10','0','0','0','0','1','4294967295','63','2','769','0','0',NULL,'1','806','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18655','Goedo_Monocle','Dragonfly Monocle','5','20','10','100','0','0','0','0','0','4294967295','63','2','512','0','50',NULL,'0','23','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18656','Wit_Pumpkin_Hat','Witch\'s Pumpkin Hat','5','20','10','300','0','0','10','0','0','4294967295','63','2','256','0','20',NULL,'1','717','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,10; bonus bStr,2; bonus bInt,2; bonus2 bMagicAddRace,RC_Undead,15; bonus2 bMagicAddRace,RC_Demon,15;','',''); REPLACE INTO `item_db` VALUES ('18657','Pegasus_Wing_Ears','Pegasus Ear Wing','5','20','10','500','0','0','1','0','0','4294967295','63','2','512','0','80',NULL,'0','568','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableHelm,0;','',''); REPLACE INTO `item_db` VALUES ('18658','Holy_Santa_Beard','Santa\'s Beard Holy','5','20','10','100','0','0','0','0','0','4294967295','63','2','1','0','0',NULL,'0','25','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); -REPLACE INTO `item_db` VALUES ('18659','Boitata_Hat','Boitata Hat','5','20','10','0','0','0','5','0','1','4294967295','63','2','768','0','0',NULL,'1','808','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('18659','Boitata_Hat','Boitata Hat','5','20','10','0','0','0','5','0','1','4294967295','63','2','768','0','0',NULL,'1','808','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus3 bAutoSpell,\"SA_FLAMELAUNCHER\",5,10; bonus3 bAutoSpell,\"AS_SONICBLOW\",5,10;','',''); REPLACE INTO `item_db` VALUES ('18660','Indi_Feather_Band','Indian Feather Headband','5','20','10','400','0','0','3','0','1','2147483646','63','2','256','0','0',NULL,'1','809','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAgi,2;','',''); REPLACE INTO `item_db` VALUES ('18661','Trident_Helmet','Trident Helmet','5','20','10','400','0','0','3','0','1','2147483646','63','2','256','0','20',NULL,'1','810','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,2;','',''); REPLACE INTO `item_db` VALUES ('18662','Antler_Fedora','Antler Fedora','5','20','10','400','0','0','3','0','0','2147483646','63','2','256','0','0',NULL,'1','811','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,3;','',''); @@ -8203,8 +8203,8 @@ REPLACE INTO `item_db` VALUES ('18669','Cowhide_Hat','Cowhide Hat','5','20','10' REPLACE INTO `item_db` VALUES ('18670','Hankie_In_Mouth','Handkerchief In Mouth','5','20','10','100','0','0','1','0','0','4294967295','63','2','1','0','12',NULL,'0','818','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bAddRaceTolerance,RC_DemiHuman,3;','',''); REPLACE INTO `item_db` VALUES ('18671','Rudolf_Hairband','Rudolf Hairband','5','20','10','200','0','0','5','0','0','4294967295','63','2','256','0','30',NULL,'1','836','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus3 bAutoSpell,AL_INCAGI,10,50; bonus2 bAddItemHealRate,Carrot,2000;','',''); REPLACE INTO `item_db` VALUES ('18672','Tare_Pope','Flap Pope','5','20','10','300','0','0','0','0','0','4294967295','63','2','256','0','0',NULL,'0','817','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,1; bonus bUnbreakableHelm,0;','',''); -REPLACE INTO `item_db` VALUES ('18673','Tare_Pope_','Chibi Pope','5','20','10','300','0','0','0','0','1','4294967295','63','2','256','0','0',NULL,'1','817','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,1; bonus bUnbreakableHelm,0;','',''); -REPLACE INTO `item_db` VALUES ('18674','Planewing_Hat','Planewing Hat','5','20','10','200','0','0','3','0','1','2147483646','63','2','256','0','0',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAgi,3;','',''); +REPLACE INTO `item_db` VALUES ('18673','Tare_Pope_','Chibi Pope','5','20','10','300','0','0','0','0','1','4294967295','63','2','256','0','0',NULL,'1','817','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bMdef,7; bonus bHealPower,5; if(getrefine()>6) bonus bHealPower,5; if(getrefine()>8) bonus bMatkRate,7; if(getrefine()>11) bonus bMatkRate,5;','',''); +REPLACE INTO `item_db` VALUES ('18674','Planewing_Hat','Planewing Hat','5','20','10','200','0','0','3','0','1','2147483646','63','2','256','0','0',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bAgi,3; bonus bAspdRate,1; bonus2 bSPLossRate,5,10000;','',''); REPLACE INTO `item_db` VALUES ('18675','Green_Apple_Hat','Green Apple Hat','5','20','10','200','0','0','3','0','1','2147483646','63','2','256','0','20',NULL,'1','11','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,2;','',''); REPLACE INTO `item_db` VALUES ('18676','Hexagon_Spectacles','Hexagon Spectacles','5','20','10','400','0','0','3','0','0','2147483646','63','2','512','0','20',NULL,'0','822','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bFlee,2;','',''); REPLACE INTO `item_db` VALUES ('18677','Cherry_Twig_In_Mouth','Cherry Twig In Mouth','5','20','10','200','0','0','0','0','0','2147483646','63','2','1','0','20',NULL,'0','823','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); @@ -8229,7 +8229,7 @@ REPLACE INTO `item_db` VALUES ('18695','Phoenix_Crown','Phoenix Crown','5','20', REPLACE INTO `item_db` VALUES ('18696','Orange_Hat','Orange Hat','5','20','10','200','0','0','3','0','0','2147483646','63','2','256','0','20',NULL,'1','841','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18697','Syringe_In_Mouth','Syringe In Mouth','5','20','10','200','0','0','0','0','0','2147483646','63','2','1','0','20',NULL,'0','842','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18698','Cheesy_Snack_In_Mouth','Cheesy Snack In Mouth','5','20','10','200','0','0','0','0','0','2147483646','63','2','1','0','20',NULL,'0','843','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); -REPLACE INTO `item_db` VALUES ('18699','Starving_Fish_Hat','Starving Fish Hat','5','20','10','1200','0','0','3','0','0','4294967295','63','2','256','0','0',NULL,'0','844','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('18699','Starving_Fish_Hat','Starving Fish Hat','5','20','10','1200','0','0','3','0','0','4294967295','63','2','256','0','0',NULL,'0','844','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus2 bSubRace,RC_Fish,15; bonus3 bAddMonsterDropItem,579,RC_Fish,5;','',''); REPLACE INTO `item_db` VALUES ('18700','Rabbit_Ribbon','Rabbit Ribbon Hat','5','20','10','500','0','0','3','0','1','4294967295','63','2','256','0','50',NULL,'1','845','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,1;','',''); REPLACE INTO `item_db` VALUES ('18701','Ancient_Civil_Man','Ancient Civil Man Hat','5','20','10','500','0','0','2','0','0','2147483646','63','2','256','0','70',NULL,'0','846','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,3; bonus bDex,2; bonus bLuk,1;','',''); REPLACE INTO `item_db` VALUES ('18702','Shaving_Cream','Shaving Cream','5','20','10','50','0','0','1','0','0','4294967295','63','2','1','0','10',NULL,'0','847','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); @@ -8238,7 +8238,7 @@ REPLACE INTO `item_db` VALUES ('18704','Drosera_Hairpin','Drosera Hairpin','5',' REPLACE INTO `item_db` VALUES ('18705','Flip_Hat','Flip Hat','5','1000','500','300','0','0','5','0','1','4294967295','63','2','256','0','0',NULL,'1','862','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18706','Can_Hat','Can Hat','5','20','10','400','0','0','3','0','0','2147483646','63','2','256','0','20',NULL,'1','851','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bLuk,3;','',''); REPLACE INTO `item_db` VALUES ('18707','Maneater_Flower_Hat','Maneater Flower Hat','5','20','10','500','0','0','3','0','0','2147483646','63','2','256','0','20',NULL,'1','852','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); -REPLACE INTO `item_db` VALUES ('18708','Candy_Hat','Candy Hat','5','20','10','200','0','0','3','0','0','2147483646','63','2','256','0','20',NULL,'1','853','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); +REPLACE INTO `item_db` VALUES ('18708','Candy_Hat','Candy Hat','5','20','10','200','0','0','3','0','0','2147483646','63','2','256','0','20',NULL,'1','853','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','skill \"AL_HEAL\",3;','',''); REPLACE INTO `item_db` VALUES ('18709','Black_Knitted_Hat','Black Knitted Hat','5','20','10','200','0','0','3','0','1','2147483646','63','2','256','0','0',NULL,'1','854','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18710','Sugared_Fruit_Stick','Sugared Fruit Stick','5','20','10','200','0','0','0','0','0','2147483646','63','2','1','0','20',NULL,'0','855','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18711','Electric_Sunglass','Electric Sunglass','5','20','10','400','0','0','3','0','0','2147483646','63','2','512','0','20',NULL,'0','856','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); @@ -8275,7 +8275,7 @@ REPLACE INTO `item_db` VALUES ('18745','Choco_Stick_In_Mouth','Choco Stick In Mo REPLACE INTO `item_db` VALUES ('18746','Chilly_Breath','Chilly Breath','5','20','10','100','0','0','0','0','0','4294967295','63','2','1','0','10',NULL,'0','885','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bInt,1;','',''); REPLACE INTO `item_db` VALUES ('18747','Eyes_Of_Ifrit','Eyes Of Ifrit','5','20','10','100','0','0','1','0','1','4294967295','63','2','512','0','0',NULL,'0','886','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,1;','',''); REPLACE INTO `item_db` VALUES ('18748','Gold_Ingot_Poring_Hat','Gold Ingot Poring Hat','5','20','10','200','0','0','3','0','1','4294967295','63','2','256','0','0',NULL,'1','887','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bDex,2; bonus bLuk,2;','',''); -REPLACE INTO `item_db` VALUES ('18749','Majoruros_Horn','Majoruros Horn','5','20','10','500','0','0','8','0','1','4294967295','63','2','256','0','0',NULL,'1','888','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,2;','',''); +REPLACE INTO `item_db` VALUES ('18749','Majoruros_Horn','Majoruros Horn','5','20','10','500','0','0','8','0','1','4294967295','63','2','256','0','0',NULL,'1','888','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bStr,2; bonus bMaxHP,100;','',''); REPLACE INTO `item_db` VALUES ('18750','Poker_Card_In_Mouth','Poker Card In Mouth','5','20','10','50','0','0','0','0','0','4294967295','63','2','1','0','10',NULL,'0','889','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18752','Cursed_Book','Cursed Book','5','0','0','0','0','0','0','0','1','4294967295','63','2','256','0','1',NULL,'1','890','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','',''); REPLACE INTO `item_db` VALUES ('18753','Tw_Rice_Ball','Rice Dumpling Hat','5','20','10','100','0','0','6','0','0','4294967295','63','2','256','0','0',NULL,'0','892','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','bonus bUnbreakableHelm,0; bonus bLuk,1;','',''); diff --git a/src/char/char.c b/src/char/char.c index 756b7397a..d97cd33a9 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -457,31 +457,16 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) || (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->robe != cp->robe) || (p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) || - (p->uniqueitem_counter != cp->uniqueitem_counter ) || (p->sex != cp->sex) + (p->uniqueitem_counter != cp->uniqueitem_counter) ) { //Save status unsigned int opt = 0; - char sex; if( p->allow_party ) opt |= OPT_ALLOW_PARTY; if( p->show_equip ) opt |= OPT_SHOW_EQUIP; - switch (p->sex) - { - case 0: - sex = 'F'; - break; - case 1: - sex = 'M'; - break; - case 99: - default: - sex = 'U'; - break; - } - if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," "`base_exp`='%u', `job_exp`='%u', `zeny`='%d'," "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," @@ -489,8 +474,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," - "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u'," - " sex = '%c'" + "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u'" " WHERE `account_id`='%d' AND `char_id` = '%d'", char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, @@ -501,7 +485,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p) mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size - p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter, sex, + p->robe,p->slotchange,opt,p->font,p->uniqueitem_counter, p->account_id, p->char_id) ) { Sql_ShowDebug(inter->sql_handle); @@ -1001,6 +985,55 @@ int char_inventory_to_sql(const struct item items[], int max, int id) { return errors; } +/** + * Returns the correct gender ID for the given character and enum value. + * + * If the per-character sex is defined but not supported by the current packetver, the database entries are corrected. + * + * @param sd Character data, if available. + * @param p Character status. + * @param sex Character sex (database enum) + * + * @retval SEX_MALE if the per-character sex is male + * @retval SEX_FEMALE if the per-character sex is female + * @retval 99 if the per-character sex is not defined or the current PACKETVER doesn't support it. + */ +int char_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex) +{ +#if PACKETVER >= 20141016 + (void)sd; (void)p; // Unused + switch (sex) { + case 'M': + return SEX_MALE; + case 'F': + return SEX_FEMALE; + case 'U': + default: + return 99; + } +#else + if (sex == 'M' || sex == 'F') { + if (!sd) { + // sd is not available, there isn't much we can do. Just return and print a warning. + ShowWarning("Character '%s' (CID: %d, AID: %d) has sex '%c', but PACKETVER does not support per-character sex. Defaulting to 'U'.\n", + p->name, p->char_id, p->account_id, sex); + return 99; + } + if ((sex == 'M' && sd->sex == SEX_FEMALE) + || (sex == 'F' && sd->sex == SEX_MALE)) { + ShowWarning("Changing sex of character '%s' (CID: %d, AID: %d) to 'U' due to incompatible PACKETVER.\n", p->name, p->char_id, p->account_id); + chr->changecharsex(p->char_id, sd->sex); + } else { + ShowInfo("Resetting sex of character '%s' (CID: %d, AID: %d) to 'U' due to incompatible PACKETVER.\n", p->name, p->char_id, p->account_id); + } + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `sex` = 'U' WHERE `char_id` = '%d'", char_db, p->char_id)) { + Sql_ShowDebug(inter->sql_handle); + } + } + return 99; +#endif +} + //===================================================================================================== // Loads the basic character rooster for the given account. Returns total buffer used. int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) @@ -1087,18 +1120,7 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) p.last_point.map = mapindex->name2id(last_map); sd->found_char[p.slot] = p.char_id; sd->unban_time[p.slot] = unban_time; - switch( sex[0] ) { - case 'M': - p.sex = 1; - break; - case 'F': - p.sex = 0; - break; - case 'U': - default: - p.sex = 99; - break; - } + p.sex = chr->mmo_gender(sd, &p, sex[0]); j += chr->mmo_char_tobuf(WBUFP(buf, j), &p); } @@ -1211,7 +1233,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL) - || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SQL->StmtFree(stmt); @@ -1224,18 +1246,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every return 0; } - switch( sex[0] ) { - case 'M': - p->sex = 1; - break; - case 'F': - p->sex = 0; - break; - case 'U': - default: - p->sex = 99; - break; - } + p->sex = chr->mmo_gender(NULL, p, sex[0]); account_id = p->account_id; @@ -2401,15 +2412,52 @@ void char_changesex(int account_id, int sex) mapif->sendall(buf, 7); } +/** + * Performs the necessary operations when changing a character's sex, such as + * correcting the job class and unequipping items, and propagating the + * information to the guild data. + * + * @param sex The new sex (SEX_MALE or SEX_FEMALE). + * @param acc The character's account ID. + * @param char_id The character ID. + * @param class_ The character's current job class. + * @param guild_id The character's guild ID. + */ +void char_change_sex_sub(int sex, int acc, int char_id, int class_, int guild_id) +{ + // job modification + if (class_ == JOB_BARD || class_ == JOB_DANCER) + class_ = (sex == SEX_MALE ? JOB_BARD : JOB_DANCER); + else if (class_ == JOB_CLOWN || class_ == JOB_GYPSY) + class_ = (sex == SEX_MALE ? JOB_CLOWN : JOB_GYPSY); + else if (class_ == JOB_BABY_BARD || class_ == JOB_BABY_DANCER) + class_ = (sex == SEX_MALE ? JOB_BABY_BARD : JOB_BABY_DANCER); + else if (class_ == JOB_MINSTREL || class_ == JOB_WANDERER) + class_ = (sex == SEX_MALE ? JOB_MINSTREL : JOB_WANDERER); + else if (class_ == JOB_MINSTREL_T || class_ == JOB_WANDERER_T) + class_ = (sex == SEX_MALE ? JOB_MINSTREL_T : JOB_WANDERER_T); + else if (class_ == JOB_BABY_MINSTREL || class_ == JOB_BABY_WANDERER) + class_ = (sex == SEX_MALE ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); + else if (class_ == JOB_KAGEROU || class_ == JOB_OBORO) + class_ = (sex == SEX_MALE ? JOB_KAGEROU : JOB_OBORO); + + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `equip`='0' WHERE `char_id`='%d'", inventory_db, char_id)) + Sql_ShowDebug(inter->sql_handle); + + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', " + "`head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", + char_db, class_, char_id)) + Sql_ShowDebug(inter->sql_handle); + if (guild_id) // If there is a guild, update the guild_member data [Skotlex] + inter_guild->sex_changed(guild_id, acc, char_id, sex); +} + int char_parse_fromlogin_changesex_reply(int fd) { - int char_id[MAX_CHARS]; - int class_[MAX_CHARS]; - int guild_id[MAX_CHARS]; - int num; + int char_id = 0, class_ = 0, guild_id = 0; int i; - char* data; - struct char_auth_node* node; + struct char_auth_node *node; + SqlStmt *stmt; int acc = RFIFOL(fd,2); int sex = RFIFOB(fd,6); @@ -2417,65 +2465,31 @@ int char_parse_fromlogin_changesex_reply(int fd) RFIFOSKIP(fd,7); // This should _never_ happen - if( acc <= 0 ) { + if (acc <= 0) { ShowError("Received invalid account id from login server! (aid: %d)\n", acc); return 1; } node = (struct char_auth_node*)idb_get(auth_db, acc); - if( node != NULL ) + if (node != NULL) node->sex = sex; // get characters - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) - Sql_ShowDebug(inter->sql_handle); - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); ++i ) - { - SQL->GetData(inter->sql_handle, 0, &data, NULL); char_id[i] = atoi(data); - SQL->GetData(inter->sql_handle, 1, &data, NULL); class_[i] = atoi(data); - SQL->GetData(inter->sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); + stmt = SQL->StmtMalloc(inter->sql_handle); + if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) + || SQL_ERROR == SQL->StmtExecute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); } - num = i; - for( i = 0; i < num; ++i ) - { - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || - class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || - class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || - class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || - class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || - class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || - class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - { - // job modification - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) - class_[i] = (sex ? JOB_BARD : JOB_DANCER); - else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) - class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); - else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) - class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); - else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) - class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); - else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) - class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); - else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) - class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); - else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); - } - - if( SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `equip`='0' WHERE `char_id`='%d'", inventory_db, char_id[i]) ) - Sql_ShowDebug(inter->sql_handle); - - if( SQL_ERROR == SQL->Query(inter->sql_handle, - "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', " - "`head_bottom`='0' WHERE `char_id`='%d'", - char_db, class_[i], char_id[i]) ) - Sql_ShowDebug(inter->sql_handle); - - if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] - inter_guild->sex_changed(guild_id[i], acc, char_id[i], sex); + SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &char_id, 0, NULL, NULL); + SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &class_, 0, NULL, NULL); + SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &guild_id, 0, NULL, NULL); + + for (i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i) { + char_change_sex_sub(sex, acc, char_id, class_, guild_id); } - SQL->FreeResult(inter->sql_handle); + SQL->StmtFree(stmt); // disconnect player if online on char-server chr->disconnect_player(acc); @@ -3439,6 +3453,49 @@ void char_ask_name_ack(int fd, int acc, const char* name, int type, int result) WFIFOSET(fd,34); } +/** + * Changes a character's sex. + * The information is updated on database, and the character is kicked if it + * currently is online. + * + * @param char_id The character's ID. + * @param sex The new sex. + * @retval 0 in case of success. + * @retval 1 in case of failure. + */ +int char_changecharsex(int char_id, int sex) +{ + int class_ = 0, guild_id = 0, account_id = 0; + char *data; + + // get character data + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`class`,`guild_id` FROM `%s` WHERE `char_id` = '%d'", char_db, char_id)) { + Sql_ShowDebug(inter->sql_handle); + return 1; + } + if (SQL->NumRows(inter->sql_handle) != 1 || SQL_ERROR == SQL->NextRow(inter->sql_handle)) { + SQL->FreeResult(inter->sql_handle); + return 1; + } + SQL->GetData(inter->sql_handle, 0, &data, NULL); account_id = atoi(data); + SQL->GetData(inter->sql_handle, 1, &data, NULL); class_ = atoi(data); + SQL->GetData(inter->sql_handle, 2, &data, NULL); guild_id = atoi(data); + SQL->FreeResult(inter->sql_handle); + + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `sex` = '%c' WHERE `char_id` = '%d'", char_db, sex == SEX_MALE ? 'M' : 'F', char_id)) { + Sql_ShowDebug(inter->sql_handle); + return 1; + } + char_change_sex_sub(sex, account_id, char_id, class_, guild_id); + + // disconnect player if online on char-server + chr->disconnect_player(account_id); + + // notify all mapservers about this change + chr->changesex(account_id, sex); + return 0; +} + void char_parse_frommap_change_account(int fd) { int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline @@ -3447,31 +3504,40 @@ void char_parse_frommap_change_account(int fd) int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) const char* name = (char*)RFIFOP(fd,6); // name of the target character int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5 changesex, 6 charban, 7 charunban - short year = RFIFOW(fd,32); - short month = RFIFOW(fd,34); - short day = RFIFOW(fd,36); - short hour = RFIFOW(fd,38); - short minute = RFIFOW(fd,40); - short second = RFIFOW(fd,42); + short year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; + int sex = SEX_MALE; + if (type == 2 || type == 6) { + year = RFIFOW(fd,32); + month = RFIFOW(fd,34); + day = RFIFOW(fd,36); + hour = RFIFOW(fd,38); + minute = RFIFOW(fd,40); + second = RFIFOW(fd,42); + } else if (type == 8) { + sex = RFIFOB(fd, 32); + } RFIFOSKIP(fd,44); SQL->EscapeStringLen(inter->sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + if(SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, esc_name)) { Sql_ShowDebug(inter->sql_handle); - else if( SQL->NumRows(inter->sql_handle) == 0 ) { + } else if (SQL->NumRows(inter->sql_handle) == 0) { + SQL->FreeResult(inter->sql_handle); result = 1; // 1-player not found - } else if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) ) { + } else if (SQL_SUCCESS != SQL->NextRow(inter->sql_handle)) { Sql_ShowDebug(inter->sql_handle); + SQL->FreeResult(inter->sql_handle); result = 1; // 1-player not found } else { int account_id, char_id; - char* data; + char *data; time_t unban_time; SQL->GetData(inter->sql_handle, 0, &data, NULL); account_id = atoi(data); SQL->GetData(inter->sql_handle, 1, &data, NULL); char_id = atoi(data); SQL->GetData(inter->sql_handle, 2, &data, NULL); unban_time = atol(data); + SQL->FreeResult(inter->sql_handle); if( chr->login_fd <= 0 ) { result = 3; // 3-login-server offline @@ -3480,40 +3546,37 @@ void char_parse_frommap_change_account(int fd) result = 2; // 2-gm level too low #endif // 0 } else { - switch( type ) { + switch (type) { case 1: // block - loginif->block_account(account_id, 5); + loginif->block_account(account_id, 5); break; case 2: // ban - loginif->ban_account(account_id, year, month, day, hour, minute, second); + loginif->ban_account(account_id, year, month, day, hour, minute, second); break; case 3: // unblock - loginif->block_account(account_id, 0); + loginif->block_account(account_id, 0); break; case 4: // unban - loginif->unban_account(account_id); + loginif->unban_account(account_id); break; case 5: // changesex - loginif->changesex(account_id); + loginif->changesex(account_id); break; - case 6: //char ban - /* handled by char server, so no redirection */ - { + case 6: // char ban - handled by char server, so no redirection chr->ban(account_id, char_id, &unban_time, year, month, day, hour, minute, second); - } break; - case 7: //char unban - chr->unban(char_id, &result); + case 7: // char unban - handled by char server, so no redirection + chr->unban(char_id, &result); + break; + case 8: // changecharsex - handled by char server, so no redirection + result = chr->changecharsex(char_id, sex); break; - } } } - SQL->FreeResult(inter->sql_handle); - // send answer if a player ask, not if the server ask - if( acc != -1 && type != 5 ) { // Don't send answer for changesex + if (acc != -1 && type != 5 && type != 8) { // Don't send answer for changesex chr->ask_name_ack(fd, acc, name, type, result); } } @@ -6028,6 +6091,7 @@ void char_defaults(void) chr->mmo_char_tosql = char_mmo_char_tosql; chr->memitemdata_to_sql = char_memitemdata_to_sql; chr->inventory_to_sql = char_inventory_to_sql; + chr->mmo_gender = char_mmo_gender; chr->mmo_chars_fromsql = char_mmo_chars_fromsql; chr->mmo_char_fromsql = char_mmo_char_fromsql; chr->mmo_char_sql_init = char_mmo_char_sql_init; @@ -6095,6 +6159,7 @@ void char_defaults(void) chr->ban = char_ban; chr->unban = char_unban; chr->ask_name_ack = char_ask_name_ack; + chr->changecharsex = char_changecharsex; chr->parse_frommap_change_account = char_parse_frommap_change_account; chr->parse_frommap_fame_list = char_parse_frommap_fame_list; chr->parse_frommap_divorce_char = char_parse_frommap_divorce_char; diff --git a/src/char/char.h b/src/char/char.h index e27aa0b44..516598fbe 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -166,6 +166,7 @@ struct char_interface { int (*mmo_char_tosql) (int char_id, struct mmo_charstatus* p); int (*memitemdata_to_sql) (const struct item items[], int max, int id, int tableswitch); int (*inventory_to_sql) (const struct item items[], int max, int id); + int (*mmo_gender) (const struct char_session_data *sd, const struct mmo_charstatus *p, char sex); int (*mmo_chars_fromsql) (struct char_session_data* sd, uint8* buf); int (*mmo_char_fromsql) (int char_id, struct mmo_charstatus* p, bool load_everything); int (*mmo_char_sql_init) (void); @@ -233,6 +234,7 @@ struct char_interface { void (*ban) (int account_id, int char_id, time_t *unban_time, short year, short month, short day, short hour, short minute, short second); void (*unban) (int char_id, int *result); void (*ask_name_ack) (int fd, int acc, const char* name, int type, int result); + int (*changecharsex) (int char_id, int sex); void (*parse_frommap_change_account) (int fd); void (*parse_frommap_fame_list) (int fd); void (*parse_frommap_divorce_char) (int fd); diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 560848c5b..b9b4704bc 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -6431,7 +6431,7 @@ ACMD(changesex) // to avoid any problem with equipment and invalid sex, equipment is unequipped. for( i=0; i<EQI_MAX; i++ ) if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3); - chrif->changesex(sd); + chrif->changesex(sd, true); return true; } diff --git a/src/map/battle.c b/src/map/battle.c index 539d3516e..31b04ad44 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -427,7 +427,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u else damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag & 8); - if ( flag & 2 && sd->bonus.arrow_atk ) + if ( flag & 2 && sd->bonus.arrow_atk && skill_id != GN_CARTCANNON ) damage += sd->bonus.arrow_atk; if ( sd->battle_status.equip_atk != 0 ) @@ -886,8 +886,6 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); if( skill_id == NC_ARMSCANNON ) damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - if( skill_id == GN_CARTCANNON ) - damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); } @@ -2541,7 +2539,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block } break; case GN_CARTCANNON: - skillratio = 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40) + 60 * skill_lv; + skillratio += -100 + (int)(50.0f * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40.0f) + 60.0f * skill_lv); break; case GN_SPORE_EXPLOSION: skillratio = 100 * skill_lv + (200 + st->int_) * status->get_lv(src) / 100; @@ -4352,6 +4350,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case PA_SACRIFICE: flag.distinct = 1; break; + case GN_CARTCANNON: case PA_SHIELDCHAIN: case GS_MAGICALBULLET: case NJ_SYURIKEN: @@ -4928,6 +4927,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list wd.damage = max(wd.damage, 1); } break; + case GN_CARTCANNON: + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id); + ATK_ADD(sd ? sd->bonus.arrow_atk : 0); + wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag)); + if ( sd && s_ele != sd->bonus.arrow_ele ) + s_ele = sd->bonus.arrow_ele; + break; case NJ_TATAMIGAESHI: ATK_RATE(200); /* Fall through */ @@ -5208,7 +5215,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list //Div fix. damage_div_fix(wd.damage, wd.div_); if ( skill_id > 0 && (skill->get_ele(skill_id, skill_lv) == ELE_NEUTRAL || flag.distinct) ) { // re-evaluate forced neutral skills - wd.damage = battle->attr_fix(src, target, wd.damage, s_ele_, tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle->attr_fix(src, target, wd.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); if ( flag.lh ) wd.damage2 = battle->attr_fix(src, target, wd.damage2, s_ele_, tstatus->def_ele, tstatus->ele_lv); } diff --git a/src/map/chrif.c b/src/map/chrif.c index da946f050..6ac7d5695 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -62,7 +62,7 @@ struct chrif_interface chrif_s; //2b0a: Incoming/Outgoing, socket_datasync() //2b0b: Outgoing, update charserv skillid2idx //2b0c: Outgoing, chrif_changeemail -> 'change mail address ...' -//2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY' +//2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY' (or char) //2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)' //2b0f: Incoming, chrif_char_ask_name_answer -> 'answer of the 2b0e' //2b10: Outgoing, chrif_updatefamelist -> 'Update the fame ranking lists and send them' @@ -744,10 +744,18 @@ bool chrif_changeemail(int id, const char *actual_email, const char *new_email) } /*========================================== - * S 2b0e <accid>.l <name>.24B <type>.w { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * S 2b0e <accid>.l <name>.24B <type>.w { <additional fields>.12B } + * { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } * Send an account modification request to the login server (via char server). - * type of operation: - * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5), 6: charban + * type of operation {additional fields}: + * 1: block { n/a } + * 2: ban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * 3: unblock { n/a } + * 4: unban { n/a } + * 5: changesex { n/a } -- use chrif_changesex + * 6: charban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * 7: charunban { n/a } + * 8: changecharsex { <sex>.b } -- use chrif_changesex *------------------------------------------*/ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) { @@ -772,14 +780,24 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope return true; } -bool chrif_changesex(struct map_session_data *sd) { +/** + * Requests a sex change (either per character or per account). + * + * @param sd The character's data. + * @param change_account Whether to change the per-account sex. + * @retval true. + */ +bool chrif_changesex(struct map_session_data *sd, bool change_account) +{ chrif_check(false); WFIFOHEAD(chrif->fd,44); WFIFOW(chrif->fd,0) = 0x2b0e; WFIFOL(chrif->fd,2) = sd->status.account_id; safestrncpy((char*)WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH); - WFIFOW(chrif->fd,30) = 5; + WFIFOW(chrif->fd,30) = change_account ? 5 : 8; + if (!change_account) + WFIFOB(chrif->fd,32) = sd->status.sex == SEX_MALE ? SEX_FEMALE : SEX_MALE; WFIFOSET(chrif->fd,44); clif->message(sd->fd, msg_sd(sd,408)); //"Disconnecting to perform change-sex request..." @@ -795,7 +813,7 @@ bool chrif_changesex(struct map_session_data *sd) { * R 2b0f <accid>.l <name>.24B <type>.w <answer>.w * Processing a reply to chrif->char_ask_name() (request to modify an account). * type of operation: - * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban + * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban, 8: changecharsex * type of answer: * 0: login-server request done * 1: player not found @@ -847,8 +865,11 @@ void chrif_changedsex(int fd) { ShowNotice("chrif_changedsex %d.\n", acc); // Path to activate this response: - // Map(start) (0x2b0e) -> Char(0x2727) -> Login + // Map(start) (0x2b0e type 5) -> Char(0x2727) -> Login // Login(0x2723) [ALL] -> Char (0x2b0d)[ALL] -> Map (HERE) + // OR + // Map(start) (0x2b03 type 8) -> Char + // Char(0x2b0d)[ALL] -> Map (HERE) // Char will usually be "logged in" despite being forced to log-out in the beginning // of this process, but there's no need to perform map-server specific response // as everything should been changed through char-server [Panikon] diff --git a/src/map/chrif.h b/src/map/chrif.h index 271fc076d..c90d00ef5 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -103,7 +103,7 @@ struct chrif_interface { bool (*char_reset_offline) (void); bool (*send_users_tochar) (void); bool (*char_online) (struct map_session_data *sd); - bool (*changesex) (struct map_session_data *sd); + bool (*changesex) (struct map_session_data *sd, bool change_account); //int (*chardisconnect) (struct map_session_data *sd); // FIXME: Commented out in clif.c, function does not exist bool (*divorce) (int partner_id1, int partner_id2); diff --git a/src/map/script.c b/src/map/script.c index 265c4a549..51bb344fe 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11254,7 +11254,7 @@ BUILDIN(changesex) TBL_PC *sd = prepareChangeSex(st); if (sd == NULL) return false; - chrif->changesex(sd); + chrif->changesex(sd, true); return true; } @@ -11266,12 +11266,7 @@ BUILDIN(changecharsex) TBL_PC *sd = prepareChangeSex(st); if (sd == NULL) return false; - if (sd->status.sex == 99) - sd->status.sex = 0; - sd->status.sex = sd->status.sex ? 0 : 1; - chrif->save(sd, 0); - if (sd->fd) - clif->authfail_fd(sd->fd, 15); + chrif->changesex(sd, false); return true; } diff --git a/src/map/skill.c b/src/map/skill.c index 4c8ecb40f..a9737f129 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7649,6 +7649,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); // Don't consume item requirements return 0; } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc index e2838b610..09d6ce1b6 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc @@ -39,6 +39,8 @@ struct { struct HPMHookPoint *HP_chr_memitemdata_to_sql_post; struct HPMHookPoint *HP_chr_inventory_to_sql_pre; struct HPMHookPoint *HP_chr_inventory_to_sql_post; + struct HPMHookPoint *HP_chr_mmo_gender_pre; + struct HPMHookPoint *HP_chr_mmo_gender_post; struct HPMHookPoint *HP_chr_mmo_chars_fromsql_pre; struct HPMHookPoint *HP_chr_mmo_chars_fromsql_post; struct HPMHookPoint *HP_chr_mmo_char_fromsql_pre; @@ -173,6 +175,8 @@ struct { struct HPMHookPoint *HP_chr_unban_post; struct HPMHookPoint *HP_chr_ask_name_ack_pre; struct HPMHookPoint *HP_chr_ask_name_ack_post; + struct HPMHookPoint *HP_chr_changecharsex_pre; + struct HPMHookPoint *HP_chr_changecharsex_post; struct HPMHookPoint *HP_chr_parse_frommap_change_account_pre; struct HPMHookPoint *HP_chr_parse_frommap_change_account_post; struct HPMHookPoint *HP_chr_parse_frommap_fame_list_pre; @@ -934,6 +938,8 @@ struct { int HP_chr_memitemdata_to_sql_post; int HP_chr_inventory_to_sql_pre; int HP_chr_inventory_to_sql_post; + int HP_chr_mmo_gender_pre; + int HP_chr_mmo_gender_post; int HP_chr_mmo_chars_fromsql_pre; int HP_chr_mmo_chars_fromsql_post; int HP_chr_mmo_char_fromsql_pre; @@ -1068,6 +1074,8 @@ struct { int HP_chr_unban_post; int HP_chr_ask_name_ack_pre; int HP_chr_ask_name_ack_post; + int HP_chr_changecharsex_pre; + int HP_chr_changecharsex_post; int HP_chr_parse_frommap_change_account_pre; int HP_chr_parse_frommap_change_account_post; int HP_chr_parse_frommap_fame_list_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc index aa279dbb4..631544248 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc @@ -23,6 +23,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(chr->mmo_char_tosql, HP_chr_mmo_char_tosql) }, { HP_POP(chr->memitemdata_to_sql, HP_chr_memitemdata_to_sql) }, { HP_POP(chr->inventory_to_sql, HP_chr_inventory_to_sql) }, + { HP_POP(chr->mmo_gender, HP_chr_mmo_gender) }, { HP_POP(chr->mmo_chars_fromsql, HP_chr_mmo_chars_fromsql) }, { HP_POP(chr->mmo_char_fromsql, HP_chr_mmo_char_fromsql) }, { HP_POP(chr->mmo_char_sql_init, HP_chr_mmo_char_sql_init) }, @@ -90,6 +91,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(chr->ban, HP_chr_ban) }, { HP_POP(chr->unban, HP_chr_unban) }, { HP_POP(chr->ask_name_ack, HP_chr_ask_name_ack) }, + { HP_POP(chr->changecharsex, HP_chr_changecharsex) }, { HP_POP(chr->parse_frommap_change_account, HP_chr_parse_frommap_change_account) }, { HP_POP(chr->parse_frommap_fame_list, HP_chr_parse_frommap_fame_list) }, { HP_POP(chr->parse_frommap_divorce_char, HP_chr_parse_frommap_divorce_char) }, diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc index ffa2cd7e2..d1bff9280 100644 --- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc @@ -482,6 +482,33 @@ int HP_chr_inventory_to_sql(const struct item items[], int max, int id) { } return retVal___; } +int HP_chr_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_chr_mmo_gender_pre ) { + int (*preHookFunc) (const struct char_session_data *sd, const struct mmo_charstatus *p, char *sex); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_mmo_gender_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_mmo_gender_pre[hIndex].func; + retVal___ = preHookFunc(sd, p, &sex); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.mmo_gender(sd, p, sex); + } + if( HPMHooks.count.HP_chr_mmo_gender_post ) { + int (*postHookFunc) (int retVal___, const struct char_session_data *sd, const struct mmo_charstatus *p, char *sex); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_mmo_gender_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_mmo_gender_post[hIndex].func; + retVal___ = postHookFunc(retVal___, sd, p, &sex); + } + } + return retVal___; +} int HP_chr_mmo_chars_fromsql(struct char_session_data *sd, uint8 *buf) { int hIndex = 0; int retVal___ = 0; @@ -2244,6 +2271,33 @@ void HP_chr_ask_name_ack(int fd, int acc, const char *name, int type, int result } return; } +int HP_chr_changecharsex(int char_id, int sex) { + int hIndex = 0; + int retVal___ = 0; + if( HPMHooks.count.HP_chr_changecharsex_pre ) { + int (*preHookFunc) (int *char_id, int *sex); + *HPMforce_return = false; + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_changecharsex_pre; hIndex++ ) { + preHookFunc = HPMHooks.list.HP_chr_changecharsex_pre[hIndex].func; + retVal___ = preHookFunc(&char_id, &sex); + } + if( *HPMforce_return ) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.chr.changecharsex(char_id, sex); + } + if( HPMHooks.count.HP_chr_changecharsex_post ) { + int (*postHookFunc) (int retVal___, int *char_id, int *sex); + for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_changecharsex_post; hIndex++ ) { + postHookFunc = HPMHooks.list.HP_chr_changecharsex_post[hIndex].func; + retVal___ = postHookFunc(retVal___, &char_id, &sex); + } + } + return retVal___; +} void HP_chr_parse_frommap_change_account(int fd) { int hIndex = 0; if( HPMHooks.count.HP_chr_parse_frommap_change_account_pre ) { diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index 42e6a574d..eddcad0d4 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -5187,15 +5187,15 @@ bool HP_chrif_char_online(struct map_session_data *sd) { } return retVal___; } -bool HP_chrif_changesex(struct map_session_data *sd) { +bool HP_chrif_changesex(struct map_session_data *sd, bool change_account) { int hIndex = 0; bool retVal___ = false; if( HPMHooks.count.HP_chrif_changesex_pre ) { - bool (*preHookFunc) (struct map_session_data *sd); + bool (*preHookFunc) (struct map_session_data *sd, bool *change_account); *HPMforce_return = false; for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_changesex_pre; hIndex++ ) { preHookFunc = HPMHooks.list.HP_chrif_changesex_pre[hIndex].func; - retVal___ = preHookFunc(sd); + retVal___ = preHookFunc(sd, &change_account); } if( *HPMforce_return ) { *HPMforce_return = false; @@ -5203,13 +5203,13 @@ bool HP_chrif_changesex(struct map_session_data *sd) { } } { - retVal___ = HPMHooks.source.chrif.changesex(sd); + retVal___ = HPMHooks.source.chrif.changesex(sd, change_account); } if( HPMHooks.count.HP_chrif_changesex_post ) { - bool (*postHookFunc) (bool retVal___, struct map_session_data *sd); + bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, bool *change_account); for(hIndex = 0; hIndex < HPMHooks.count.HP_chrif_changesex_post; hIndex++ ) { postHookFunc = HPMHooks.list.HP_chrif_changesex_post[hIndex].func; - retVal___ = postHookFunc(retVal___, sd); + retVal___ = postHookFunc(retVal___, sd, &change_account); } } return retVal___; |