From 56490400ca271690470f7b0496256d417805fe90 Mon Sep 17 00:00:00 2001 From: Tabasco Date: Wed, 24 Apr 2013 15:58:51 -0500 Subject: [PATCH 1/9] Dungeon Crawl custom code merge Added numerous modding hooks. Added rules: Character:KeepLevelOverMax - Don't delevel a character if they are found to be over max level rule. Spells:UseCHAScribeHack - Optionally omit spells with CHA in effect12 when using scribespells and traindiscs Combat:MonkACBonusWeight - Adjust the weight threshold for monk AC bonus Combat:ClientStunLevel - Adjust the level clients kicks and bashes start to roll for stuns Combat;QuiverWRHasteDiv - Adjust the divisor applied to weight reduction for haste calcs Combat:UseArcheryBonusRoll - Make archery stationary bonus a roll Combat:ArcheryBonusChance - Archery stationary bonus chance Added account flags and associated perl wrappers Added EVENT_ITEM_TICK for interactive items Added EVENT_DUEL_WIN and EVENT_DUEL_LOSE, which exports $enemyname and $enemyid Added timer and interval to console worldshutdown command Added EQW interface for worldshutdown and server-wide messages --- common/ruletypes.h | 10 +- common/spdat.cpp | 5 + common/spdat.h | 1 + .../git/required/2013_04_24_Account_Flags.sql | 11 ++ .../sql/git/required/2013_04_24_Item_Tick.sql | 13 ++ world/EQW.cpp | 8 + world/EQW.h | 2 + world/console.cpp | 23 ++- world/perl_EQW.cpp | 53 ++++++ world/zonelist.cpp | 34 +++- world/zonelist.h | 3 +- zone/CMakeLists.txt | 1 + zone/attack.cpp | 65 ++++++- zone/client.cpp | 133 +++++++++++++- zone/client.h | 35 +++- zone/client_mods.cpp | 3 + zone/client_packet.cpp | 68 +++++++ zone/client_process.cpp | 6 + zone/embparser.cpp | 20 ++- zone/entity.cpp | 7 + zone/event_codes.h | 5 +- zone/exp.cpp | 13 +- zone/loottables.cpp | 6 + zone/mob.cpp | 20 ++- zone/mob.h | 25 +++ zone/mod_functions.cpp | 72 ++++++++ zone/mod_functions_base.cpp | 72 ++++++++ zone/npc.cpp | 74 +++++++- zone/npc.h | 10 +- zone/perl_client.cpp | 88 +++++++++ zone/perl_mob.cpp | 34 +++- zone/perl_npc.cpp | 65 ++++++- zone/perlparser.cpp | 34 ++++ zone/pets.cpp | 5 +- zone/questmgr.cpp | 12 +- zone/questmgr.h | 2 + zone/spawn2.cpp | 11 +- zone/spawn2.h | 6 +- zone/special_attacks.cpp | 57 +++++- zone/spell_effects.cpp | 77 ++++---- zone/spells.cpp | 169 ++++++++++++------ zone/tradeskills.cpp | 6 + zone/tribute.cpp | 4 + zone/zone.cpp | 88 ++++++++- zone/zone.h | 21 +++ 45 files changed, 1321 insertions(+), 156 deletions(-) create mode 100644 utils/sql/git/required/2013_04_24_Account_Flags.sql create mode 100644 utils/sql/git/required/2013_04_24_Item_Tick.sql create mode 100644 zone/mod_functions.cpp create mode 100644 zone/mod_functions_base.cpp diff --git a/common/ruletypes.h b/common/ruletypes.h index c7a7eb854..e5156c474 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -95,7 +95,7 @@ RULE_BOOL ( Character, CheckCursorEmptyWhenLooting, true ) // If true, a player RULE_BOOL ( Character, MaintainIntoxicationAcrossZones, true ) // If true, alcohol effects are maintained across zoning and logging out/in. RULE_BOOL ( Character, EnableDiscoveredItems, true ) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. RULE_BOOL ( Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. - +RULE_BOOL ( Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) @@ -291,7 +291,8 @@ RULE_INT ( Spells, MaxCastTimeReduction, 50) //Max percent your spell cast time RULE_INT ( Spells, RootBreakFromSpells, 20) //Chance for root to break when cast on. RULE_INT ( Spells, DeathSaveCharismaMod, 3) //Determines how much charisma effects chance of death save firing. RULE_INT ( Spells, DivineInterventionHeal, 8000) //Divine intervention heal amount. -RULE_BOOL( Spells, AdditiveBonusValues, false) //Allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. (ie Add together all Cleave Effects) +RULE_BOOL ( Spells, AdditiveBonusValues, false) //Allow certain bonuses to be calculated by adding together the value from each item, instead of taking the highest value. (ie Add together all Cleave Effects) +RULE_BOOL ( Spells, UseCHAScribeHack, false) //ScribeSpells and TrainDiscs quest functions will ignore entries where field 12 is CHA. What's the best way to do this? RULE_CATEGORY_END() RULE_CATEGORY( Combat ) @@ -361,6 +362,11 @@ RULE_INT ( Combat, NPCFlurryChance, 20) // Chance for NPC to flurry. RULE_BOOL (Combat,TauntOverLevel, 1) //Allows you to taunt NPC's over warriors level. RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's not maxed you lose this % chance to taunt. RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain. +RULE_INT ( Combat, MonkACBonusWeight, 15) +RULE_INT ( Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target +RULE_INT ( Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers +RULE_BOOL ( Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll +RULE_INT ( Combat, ArcheryBonusChance, 50) RULE_CATEGORY_END() RULE_CATEGORY( NPC ) diff --git a/common/spdat.cpp b/common/spdat.cpp index 82e262de1..3553d4866 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1102,3 +1102,8 @@ bool IsShortDurationBuff(uint16 spell_id) return false; } +//DCBOOKMARK +const char* GetSpellName(int16 spell_id) +{ + return( spells[spell_id].name ); +} diff --git a/common/spdat.h b/common/spdat.h index 45a7cc552..a936f9975 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -806,5 +806,6 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id); uint32 GetNimbusEffect(uint16 spell_id); int32 GetFuriousBash(uint16 spell_id); bool IsShortDurationBuff(uint16 spell_id); +const char *GetSpellName(int16 spell_id); #endif diff --git a/utils/sql/git/required/2013_04_24_Account_Flags.sql b/utils/sql/git/required/2013_04_24_Account_Flags.sql new file mode 100644 index 000000000..522a9fa49 --- /dev/null +++ b/utils/sql/git/required/2013_04_24_Account_Flags.sql @@ -0,0 +1,11 @@ +-- +-- Table structure for table `account_flags` +-- + +CREATE TABLE IF NOT EXISTS `account_flags` ( + `p_accid` int(10) unsigned NOT NULL, + `p_flag` varchar(50) NOT NULL, + `p_value` varchar(80) NOT NULL, + PRIMARY KEY (`p_accid`,`p_flag`), + KEY `p_accid` (`p_accid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/utils/sql/git/required/2013_04_24_Item_Tick.sql b/utils/sql/git/required/2013_04_24_Item_Tick.sql new file mode 100644 index 000000000..4e3e1c41d --- /dev/null +++ b/utils/sql/git/required/2013_04_24_Item_Tick.sql @@ -0,0 +1,13 @@ +-- +-- Table structure for table `item_tick` +-- + +CREATE TABLE IF NOT EXISTS `item_tick` ( + `it_itemid` int(11) NOT NULL, + `it_chance` int(11) NOT NULL, + `it_level` int(11) NOT NULL, + `it_id` int(11) NOT NULL AUTO_INCREMENT, + `it_qglobal` varchar(50) NOT NULL, + `it_bagslot` tinyint(4) NOT NULL, + PRIMARY KEY (`it_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/world/EQW.cpp b/world/EQW.cpp index c97fcd652..0aafbdbb3 100644 --- a/world/EQW.cpp +++ b/world/EQW.cpp @@ -459,6 +459,14 @@ void EQW::ResolveBug(const char *id) { safe_delete_array(query); } +//DCBOOKMARK +void EQW::SendMessage(uint32 type, const char *msg) { + zoneserver_list.SendEmoteMessage(0, 0, 0, type, msg); +} + +void EQW::WorldShutDown(uint32 time, uint32 interval) { + zoneserver_list.WorldShutDown(time, interval); +} #endif //EMBPERL diff --git a/world/EQW.h b/world/EQW.h index 4580a3998..788fc41a9 100644 --- a/world/EQW.h +++ b/world/EQW.h @@ -78,6 +78,8 @@ public: map GetBugDetails(const char *id); void ResolveBug(const char *id); + void SendMessage(uint32 type, const char *msg); + void WorldShutDown(uint32 time, uint32 interval); //END PERL EXPORT protected: diff --git a/world/console.cpp b/world/console.cpp index 15d580660..9bcf410d1 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -722,11 +722,24 @@ void Console::ProcessCommand(const char* command) { } } else if (strcasecmp(sep.arg[0], "worldshutdown") == 0 && admin >= consoleWorldStatus) { - ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll); - zoneserver_list.SendPacket(pack); - delete pack; - SendMessage(1, "Sending shutdown packet... goodbye."); - CatchSignal(0); + int32 time, interval; + if(sep.IsNumber(1) && sep.IsNumber(2) && ((time=atoi(sep.arg[1]))>0) && ((interval=atoi(sep.arg[2]))>0)) { + zoneserver_list.WorldShutDown(time, interval); + } + else if(strcasecmp(sep.arg[1], "now") == 0) { + zoneserver_list.WorldShutDown(0, 0); + } + else if(strcasecmp(sep.arg[1], "disable") == 0) { + SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World shutdown aborted."); + zoneserver_list.SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World shutdown aborted."); + zoneserver_list.shutdowntimer->Disable(); + zoneserver_list.reminder->Disable(); + } + else { + SendMessage(1, "Usage: worldshutdown [now] [disable] ([time] [interval])"); + //Go ahead and shut down since that's what this used to do when invoked this way. + zoneserver_list.WorldShutDown(0, 0); + } } else if (strcasecmp(sep.arg[0], "lock") == 0 && admin >= consoleLockStatus) { WorldConfig::LockWorld(); diff --git a/world/perl_EQW.cpp b/world/perl_EQW.cpp index 6f748d720..bab4b6ca6 100644 --- a/world/perl_EQW.cpp +++ b/world/perl_EQW.cpp @@ -969,6 +969,57 @@ XS(XS_EQW_ResolveBug) XSRETURN_EMPTY; } +XS(XS_EQW_SendMessage); /* prototype to pass -Wmissing-prototypes */ +XS(XS_EQW_SendMessage) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: EQW::SendMessage(THIS, type, message)"); + { + EQW * THIS; + dXSTARG; + uint32 msgtype = (uint32)SvUV(ST(1)); + char* msg = (char *)SvPV_nolen(ST(2)); + + if (sv_derived_from(ST(0), "EQW")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(EQW *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type EQW"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->SendMessage(msgtype, msg); + } + XSRETURN_EMPTY; +} + +XS(XS_EQW_WorldShutDown); /* prototype to pass -Wmissing-prototypes */ +XS(XS_EQW_WorldShutDown) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: EQW::WorldShutDown(THIS, time, interval)"); + { + EQW * THIS; + dXSTARG; + uint32 time = (uint32)SvUV(ST(1)); + uint32 interval = (uint32)SvUV(ST(2)); + + if (sv_derived_from(ST(0), "EQW")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(EQW *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type EQW"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->WorldShutDown(time, interval); + } + XSRETURN_EMPTY; +} #ifdef __cplusplus extern "C" @@ -1020,6 +1071,8 @@ XS(boot_EQW) newXSproto(strcpy(buf, "ListBugs"), XS_EQW_ListBugs, file, "$$"); newXSproto(strcpy(buf, "GetBugDetails"), XS_EQW_GetBugDetails, file, "$$"); newXSproto(strcpy(buf, "ResolveBug"), XS_EQW_ResolveBug, file, "$$"); + newXSproto(strcpy(buf, "SendMessage"), XS_EQW_SendMessage, file, "$$$"); + newXSproto(strcpy(buf, "WorldShutDown"), XS_EQW_WorldShutDown, file, "$$$"); XSRETURN_YES; } diff --git a/world/zonelist.cpp b/world/zonelist.cpp index c19a55c4d..c9b23a343 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -716,14 +716,30 @@ void ZSList::GetZoneIDList(vector &zones) { } +//DCBOOKMARK +void ZSList::WorldShutDown(uint32 time, uint32 interval) +{ + if( time > 0 ) { + SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down in %i seconds, everyone log out before this time.",time); + time *= 1000; + interval *= 1000; + if(interval < 5000) { interval = 5000; } - - - - - - - - - + shutdowntimer->SetTimer(time); + reminder->SetTimer(interval-1000); + reminder->SetAtTrigger(interval); + shutdowntimer->Start(); + reminder->Start(); + } + else { + SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down, everyone log out now."); + ServerPacket* pack = new ServerPacket; + pack->opcode = ServerOP_ShutdownAll; + pack->size=0; + SendPacket(pack); + safe_delete(pack); + Process(); + CatchSignal(2); + } +} diff --git a/world/zonelist.h b/world/zonelist.h index cd8b36943..6a4b074a4 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -56,7 +56,8 @@ public: int GetZoneCount(); void GetZoneIDList(std::vector &zones); - + void WorldShutDown(uint32 time, uint32 interval); + protected: uint32 NextID; LinkedList list; diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 7079942ab..6f3ad68ee 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -84,6 +84,7 @@ SET(zone_sources zonedb.cpp zonedbasync.cpp zoning.cpp + mod_functions.cpp ) SET(zone_headers diff --git a/zone/attack.cpp b/zone/attack.cpp index 1bbb6efa8..e91fccba0 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -318,6 +318,9 @@ bool Mob::CheckHitChance(Mob* other, SkillType skillinuse, int Hand, int16 chanc if(skillinuse == ARCHERY) chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f; + //DCBOOKMARK + chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); + // Chance to hit; Max 95%, Min 30% if(chancetohit > 1000) { //if chance to hit is crazy high, that means a discipline is in use, and let it stay there @@ -396,6 +399,8 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/60.0 + (GetDEX()/200); bonus *= riposte_chance; + //DCBOOKMARK + bonus = mod_riposte_chance(bonus, attacker); RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block } } @@ -434,6 +439,8 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/35.0 + (GetDEX()/200); + //DCBOOKMARK + bonus = mod_block_chance(bonus, attacker); RollTable[1] = RollTable[0] + (bonus * block_chance); } } @@ -485,6 +492,8 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/60.0 + (GetDEX()/200); bonus *= parry_chance; + //DCBOOKMARK + bonus = mod_parry_chance(bonus, attacker); RollTable[2] = RollTable[1] + bonus; } } @@ -507,6 +516,8 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/60.0 + (GetAGI()/200); bonus *= dodge_chance; + //DCBOOMKAR + bonus = mod_dodge_chance(bonus, attacker); RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25); } } @@ -555,6 +566,11 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) int shield_ac = 0; int armor = 0; float weight = 0.0; + + //DCBOOKMARK + float monkweight = RuleI(Combat, MonkACBonusWeight); + monkweight = mod_monk_weight(monkweight, attacker); + if(IsClient()) { armor = CastToClient()->GetRawACNoShield(shield_ac); @@ -576,7 +592,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) { softcap = RuleI(Combat, ClothACSoftcap); } - else if(GetClass() == MONK && weight <= 15.0) + else if(GetClass() == MONK && weight <= monkweight) { softcap = RuleI(Combat, MonkACSoftcap); } @@ -603,7 +619,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) { softcap_armor = softcap_armor * RuleR(Combat, WarriorACSoftcapReturn); } - else if(GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || (GetClass() == MONK && weight <= 15.0)) + else if(GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || (GetClass() == MONK && weight <= monkweight)) { softcap_armor = softcap_armor * RuleR(Combat, KnightACSoftcapReturn); } @@ -637,6 +653,9 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) } mitigation_rating *= 0.847; + //DCBOOKMARK + mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); + if(attacker->IsClient()) { attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(OFFENSE)*1.345)); @@ -646,6 +665,9 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) attack_rating = (attacker->GetATK() + (attacker->GetSkill(OFFENSE)*1.345) + ((attacker->GetSTR()-66) * 0.9)); } + //DCBOOKMARK + attack_rating = attacker->mod_attack_rating(attack_rating, this); + float d = 10.0; float mit_roll = MakeRandomFloat(0, mitigation_rating); float atk_roll = MakeRandomFloat(0, attack_rating); @@ -669,6 +691,9 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) if(thac20 > thac20cap) { thac20 = thac20cap; + + + } d += 10 * (m_diff / thac20); } @@ -1221,6 +1246,9 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b else damage = MakeRandomInt(min_hit, max_hit); + //DCBOOKMARK + damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); + mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); @@ -1458,6 +1486,10 @@ void Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ { if (killerMob->IsNPC()) { parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); + + //DCBOOKMARK + mod_client_death_npc(killerMob); + uint16 emoteid = killerMob->GetEmoteID(); if(emoteid != 0) killerMob->CastToNPC()->DoNPCEmote(KILLEDPC,emoteid); @@ -1473,6 +1505,10 @@ void Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ killerMob->CastToClient()->SetDueling(false); killerMob->CastToClient()->SetDuelTarget(0); entity_list.DuelMessage(killerMob,this,false); + + //DCBOOKMARK + mod_client_death_duel(killerMob); + } else { //otherwise, we just died, end the duel. Mob* who = entity_list.GetMob(GetDuelTarget()); @@ -1844,6 +1880,9 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool damage = (max_dmg+eleBane); } + //DCBOOKMARK + damage = mod_npc_damage(damage, skillinuse, Hand, &weapon_inst, other); + int32 hate = damage; if(IsPet()) { @@ -2042,7 +2081,7 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski entity_list.QueueClients(killerMob, app, false); if(respawn2) { - respawn2->DeathReset(); + respawn2->DeathReset(1); } if (killerMob) { @@ -2097,6 +2136,10 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski for (int i = 0; i < MAX_RAID_MEMBERS; i++) { if (kr->members[i].member != NULL) { // If Group Member is Client parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0); + + //DCBOOKMARK + mod_npc_killed_merit(kr->members[i].member); + if(RuleB(TaskSystem, EnableTaskSystem)) kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); PlayerCount++; @@ -2137,6 +2180,10 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski if (kg->members[i] != NULL && kg->members[i]->IsClient()) { // If Group Member is Client Client *c = kg->members[i]->CastToClient(); parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + + //DCBOOKMARK + mod_npc_killed_merit(c); + if(RuleB(TaskSystem, EnableTaskSystem)) c->UpdateTasksOnKill(GetNPCTypeID()); @@ -2181,6 +2228,10 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski } /* Send the EVENT_KILLED_MERIT event */ parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); + + //DCBOOKMARK + mod_npc_killed_merit(give_exp_client); + if(RuleB(TaskSystem, EnableTaskSystem)) give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); @@ -2311,6 +2362,10 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski if(killerMob) { Mob *oos = killerMob->GetOwnerOrSelf(); parse->EventNPC(EVENT_DEATH, this, oos, "", 0); + + //DCBOOKMARK + mod_npc_killed(oos); + uint16 emoteid = this->GetEmoteID(); if(emoteid != 0) this->DoNPCEmote(ONDEATH,emoteid); @@ -3402,8 +3457,8 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons if (damage > 0 && ((skill_used == BASH || skill_used == KICK) && attacker)) { // NPCs can stun with their bash/kick as soon as they recieve it. - // Clients can stun mobs under level 56 with their bash/kick when they get level 55 or greater. - if((attacker->IsNPC()) || (attacker->IsClient() && attacker->GetLevel() >= 55 && GetLevel() < 56)) + // Clients can stun mobs under level 56 with their bash/kick when they get level 55 or greater. -- DCBOOKMARK for rules + if( attacker->IsNPC() || (attacker->IsClient() && attacker->GetLevel() >= RuleI(Combat, ClientStunLevel) && GetLevel() < RuleI(Spells, BaseImmunityLevel)) ) { if (MakeRandomInt(0,99) < (RuleI(Character, NPCBashKickStunChance)) || attacker->IsClient()) { diff --git a/zone/client.cpp b/zone/client.cpp index b468f922e..f2fdfb46e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -166,7 +166,8 @@ Client::Client(EQStreamInterface* ieqs) qglobal_purge_timer(30000), TrackingTimer(2000), RespawnFromHoverTimer(0), - merc_timer(RuleI(Mercs, UpkeepIntervalMS)) + merc_timer(RuleI(Mercs, UpkeepIntervalMS)), + ItemTickTimer(10000) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; @@ -325,6 +326,8 @@ Client::Client(EQStreamInterface* ieqs) } MaxXTargets = 5; XTargetAutoAddHaters = true; + //DCBOOKMARK + LoadAccountFlags(); } Client::~Client() { @@ -842,6 +845,9 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s safe_delete(pack); } + //DCBOOKMARK - Return true to proceed, false to return + if(!mod_client_message(message, chan_num)) { return; } + // Garble the message based on drunkness if (m_pp.intoxication > 0) { GarbleMessage(message, (int)(m_pp.intoxication / 3)); @@ -2334,10 +2340,11 @@ bool Client::CheckIncreaseSkill(SkillType skillid, Mob *against_who, int chancem if(against_who) { - if(against_who->SpecAttacks[IMMUNE_AGGRO] || against_who->IsClient() || - GetLevelCon(against_who->GetLevel()) == CON_GREEN) + if( against_who->SpecAttacks[IMMUNE_AGGRO] || against_who->IsClient() || + GetLevelCon(against_who->GetLevel()) == CON_GREEN ) { - return false; + //DCBOOKMARK - false by default + return mod_can_increase_skill(skillid, against_who); } } @@ -2349,6 +2356,10 @@ bool Client::CheckIncreaseSkill(SkillType skillid, Mob *against_who, int chancem if (Chance < 1) Chance = 1; // Make it always possible Chance = (Chance * RuleI(Character, SkillUpModifier) / 100); + + //DCBOOKMARK + Chance = mod_increase_skill_chance(Chance, against_who); + if(MakeRandomFloat(0, 99) < Chance) { SetSkill(skillid, GetRawSkill(skillid) + 1); @@ -2717,6 +2728,9 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ max_percent = 70 + 10 * maxHPBonus; } + //DCBOOKMARK + max_percent = mod_bindwound_percent(max_percent, bindmob); + int max_hp = bindmob->GetMaxHP()*max_percent/100; // send bindmob new hp's @@ -2735,7 +2749,10 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound; bindhps += bindhps*bindBonus / 100; - + + //DCBOOKMARK + bindhps = mod_bindwound_hp(bindhps, bindmob); + //if the bind takes them above the max bindable //cap it at that value. Dont know if live does it this way //but it makes sense to me. @@ -7606,3 +7623,109 @@ some day. } return 0; } + +//DCBOOKMARK +void Client::LoadAccountFlags() +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + accountflags.clear(); + MakeAnyLenString(&query, "SELECT p_flag, p_value FROM account_flags WHERE p_accid = '%d'", account_id); + if(database.RunQuery(query, strlen(query), errbuf, &result)) + { + while(row = mysql_fetch_row(result)) + { + std::string fname(row[0]); + std::string fval(row[1]); + accountflags[fname] = fval; + } + mysql_free_result(result); + } + else + { + std::cerr << "Error in LoadAccountFlags query '" << query << "' " << errbuf << std::endl; + } + safe_delete_array(query); +} + +void Client::SetAccountFlag(std::string flag, std::string val) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + MakeAnyLenString(&query, "REPLACE INTO account_flags (p_accid, p_flag, p_value) VALUES( '%d', '%s', '%s')", account_id, flag.c_str(), val.c_str()); + if(!database.RunQuery(query, strlen(query), errbuf)) + { + std::cerr << "Error in SetAccountFlags query '" << query << "' " << errbuf << std::endl; + } + safe_delete_array(query); + + accountflags[flag] = val; +} + +std::string Client::GetAccountFlag(std::string flag) +{ + return(accountflags[flag]); +} + +void Client::TickItemCheck() +{ + int i; + + //Scan equip slots for items + for(i = 0; i <= 21; i++) + { + TryItemTick(i); + } + //Scan main inventory + cursor + for(i = 22; i < 31; i++) + { + TryItemTick(i); + } + //Scan bags + for(i = 251; i < 340; i++) + { + TryItemTick(i); + } +} + +void Client::TryItemTick(int slot) +{ + int iid = 0; + const ItemInst* inst = m_inv[slot]; + if(inst == 0) { return; } + + iid = inst->GetID(); + + if(zone->tick_items.count(iid) > 0) + { + if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot < 22) ) + { + ItemInst* e_inst = (ItemInst*)inst; + parse->EventItem(EVENT_ITEM_TICK, this, e_inst, e_inst->GetID(), slot); + } + } + + //Only look at augs in main inventory + if(slot > 21) { return; } + + for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) + { + ItemInst * a_inst = inst->GetAugment(x); + if(!a_inst) { continue; } + + iid = a_inst->GetID(); + + if(zone->tick_items.count(iid) > 0) + { + if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) ) + { + ItemInst* e_inst = (ItemInst*)a_inst; + parse->EventItem(EVENT_ITEM_TICK, this, e_inst, e_inst->GetID(), slot); + } + } + } +} diff --git a/zone/client.h b/zone/client.h index 2d7aa2ac7..a2a9c2441 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1133,6 +1133,36 @@ public: void DuplicateLoreMessage(uint32 ItemID); void GarbleMessage(char *, uint8); + //DCBOOKMARK + void TickItemCheck(); + void TryItemTick(int slot); + int16 GetActSTR() { return( min(GetMaxSTR(), GetSTR()) ); } + int16 GetActSTA() { return( min(GetMaxSTA(), GetSTA()) ); } + int16 GetActDEX() { return( min(GetMaxDEX(), GetDEX()) ); } + int16 GetActAGI() { return( min(GetMaxAGI(), GetAGI()) ); } + int16 GetActINT() { return( min(GetMaxINT(), GetINT()) ); } + int16 GetActWIS() { return( min(GetMaxWIS(), GetWIS()) ); } + int16 GetActCHA() { return( min(GetMaxCHA(), GetCHA()) ); } + void LoadAccountFlags(); + void SetAccountFlag(std::string flag, std::string val); + std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillType); + int mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other); + bool mod_client_message(char* message, uint8 chan_num); + bool mod_can_increase_skill(SkillType skillid, Mob* against_who); + int16 mod_increase_skill_chance(int16 chance, Mob* against_who); + int mod_bindwound_percent(int max_percent, Mob* bindmob); + int mod_bindwound_hp(int bindhps, Mob* bindmob); + int mod_client_haste(int h); + void mod_consider(Mob* tmob, Consider_Struct* con); + bool mod_saylink(const std::string&, bool silentsaylink); + int16 mod_pet_power(int16 act_power, uint16 spell_id); + float mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec); + float mod_tradeskill_skillup(float chance_stage2); + int32 mod_tribute_item_value(int32 pts); + void mod_client_death_npc(Mob* killerMob); + void mod_client_death_duel(Mob* killerMob); + void mod_client_death_env(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1434,8 +1464,11 @@ private: uint8 MaxXTargets; bool XTargetAutoAddHaters; - struct XTarget_Struct XTargets[XTARGET_HARDCAP]; + struct XTarget_Struct XTargets[XTARGET_HARDCAP]; + //DCBOOKMARK + Timer ItemTickTimer; + std::map accountflags; }; #include "parser.h" diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index f9242bc85..e9f0bef0b 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1415,6 +1415,9 @@ int Client::CalcHaste() { h += spellbonuses.hastetype3; h += ExtraHaste; //GM granted haste. + //DCBOOKMARK + h = mod_client_haste(h); + if (spellbonuses.inhibitmelee){ if (h >= 0) h -= spellbonuses.inhibitmelee; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c27ee0a73..e9faaa557 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2076,6 +2076,30 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } } + //DCBOOKMARK + int r; + bool tryaug = false; + ItemInst* clickaug = 0; + Item_Struct* augitem = 0; + + for(r = 0; r < MAX_AUGMENT_SLOTS; r++) { + const ItemInst* aug_i = inst->GetAugment(r); + if(!aug_i) + continue; + const Item_Struct* aug = aug_i->GetItem(); + if(!aug) + continue; + + if ( (aug->Click.Type == ET_ClickEffect) || (aug->Click.Type == ET_Expendable) || (aug->Click.Type == ET_EquipClick) || (aug->Click.Type == ET_ClickEffect2) ) + { + tryaug = true; + clickaug = (ItemInst*)aug_i; + augitem = (Item_Struct*)aug; + spell_id = aug->Click.Effect; + break; + } + } + if((spell_id <= 0) && (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink && item->ItemType != ItemTypeAlcohol && item->ItemType != ItemTypeSpell)) { LogFile->write(EQEMuLog::Debug, "Item with no effect right clicked by %s",GetName()); @@ -2123,6 +2147,39 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } } + else if (tryaug) //DCBOOKMARK + { + if (clickaug->GetCharges() == 0) + { + //Message(0, "This item is out of charges."); + Message_StringID(13, ITEM_OUT_OF_CHARGES); + return; + } + if(GetLevel() >= augitem->Click.Level2) + { + if(parse->ItemHasQuestSub(clickaug, "EVENT_ITEM_CLICK_CAST")) + { + //TODO: need to enforce and set recast timers here because the spell may not be cast. + parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, clickaug->GetID(), slot_id); + inst = m_inv[slot_id]; + if (!inst) + { + // Item was deleted by the perl event + return; + } + } + else + { + //We assume augs aren't consumable + CastSpell(augitem->Click.Effect, target_id, 10, augitem->CastTime, 0, 0, slot_id); + } + } + else + { + Message_StringID(13, ITEMS_INSUFFICIENT_LEVEL); + return; + } + } else { if(GetClientVersion() >= EQClientSoD && !inst->IsEquipable(GetBaseRace(),GetClass())) @@ -2605,6 +2662,9 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) con->faction = FACTION_DUBIOUS; } + //DCBOOKMARK + mod_consider(tmob, con); + QueuePacket(outapp); safe_delete(outapp); return; @@ -3200,6 +3260,9 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) if((response).size() > 0) { + //DCBOOKMARK + if( !mod_saylink(response, silentsaylink) ) { return; } + if(this->GetTarget() && this->GetTarget()->IsNPC()) { if(silentsaylink) @@ -7714,7 +7777,12 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) SetHP(GetHP() - damage); if(GetHP() <= 0) + { + //DCBOOKMARK + mod_client_death_env(); + Death(0, 32000, SPELL_UNKNOWN, HAND_TO_HAND); + } SendHPUpdate(); return; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 6a28722a9..14af5edce 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -645,6 +645,12 @@ bool Client::Process() { --m_pp.intoxication; CalcBonuses(); } + + //DCBOOKMARK + if(ItemTickTimer.Check()) + { + TickItemCheck(); + } } } diff --git a/zone/embparser.cpp b/zone/embparser.cpp index dc77b4e75..8503f702c 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -93,7 +93,10 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_CLICK_OBJECT", "EVENT_DISCOVER_ITEM", "EVENT_DISCONNECT", - "EVENT_CONNECT" + "EVENT_CONNECT", + "EVENT_ITEM_TICK", + "EVENT_DUEL_WIN", + "EVENT_DUEL_LOSE" }; extern Zone* zone; @@ -739,6 +742,13 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d ExportVar(packagename.c_str(), "itemname", iteminst->GetItem()->Name); break; } + case EVENT_ITEM_TICK: + { + ExportVar(packagename.c_str(), "itemid", objid); + ExportVar(packagename.c_str(), "itemname", iteminst->GetItem()->Name); + ExportVar(packagename.c_str(), "invslot", extradata); + break; + } case EVENT_ITEM_CLICK_CAST: case EVENT_ITEM_CLICK: { ExportVar(packagename.c_str(), "itemid", objid); @@ -796,6 +806,14 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d break; } + case EVENT_DUEL_WIN: + case EVENT_DUEL_LOSE: + { + ExportVar(packagename.c_str(), "enemyname", data); + ExportVar(packagename.c_str(), "enemyid", extradata); + break; + } + //nothing special about these events case EVENT_DEATH: case EVENT_SPAWN: diff --git a/zone/entity.cpp b/zone/entity.cpp index 660db5d7d..a9281c247 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1888,6 +1888,13 @@ void EntityList::QueueClientsStatus(Mob* sender, const EQApplicationPacket* app, void EntityList::DuelMessage(Mob* winner, Mob* loser, bool flee) { LinkedListIterator iterator(client_list); + //DCBOOKMARK + if(winner->GetLevelCon(winner->GetLevel(), loser->GetLevel()) > 2) + { + parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID()); + parse->EventPlayer(EVENT_DUEL_LOSE, loser->CastToClient(), winner->GetName(), winner->CastToClient()->CharacterID()); + } + iterator.Reset(); while(iterator.MoreElements()) { Client *cur = iterator.GetData(); diff --git a/zone/event_codes.h b/zone/event_codes.h index 3a2975693..3a6d9363b 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -58,7 +58,10 @@ typedef enum { EVENT_DISCOVER_ITEM, EVENT_DISCONNECT, EVENT_CONNECT, - + EVENT_ITEM_TICK, + EVENT_DUEL_WIN, + EVENT_DUEL_LOSE, + _LargestEventID } QuestEventID; diff --git a/zone/exp.cpp b/zone/exp.cpp index 4d43b64af..f588643bb 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -289,7 +289,16 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { if(check_level > maxlevel) { check_level = maxlevel; - set_exp = GetEXPForLevel(maxlevel); + + //DCBOOKMARK + if(RuleB(Character, KeepLevelOverMax)) + { + set_exp = GetEXPForLevel(GetLevel()+1); + } + else + { + set_exp = GetEXPForLevel(maxlevel); + } } if(RuleB(Character, PerCharacterQglobalMaxLevel)){ @@ -665,4 +674,4 @@ uint32 Client::GetCharMaxLevelFromQGlobal() { } return false; // Default is false -} \ No newline at end of file +} diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 75e442afc..94841d492 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -376,3 +376,9 @@ void NPC::AddLootTable() { } } +//DCBOOKMARK +void NPC::AddLootTable(uint32 ldid) { + if (npctype_id != 0) { // check if it's a GM spawn + database.AddLootTableToNPC(this,ldid, &itemlist, &copper, &silver, &gold, &platinum); + } +} diff --git a/zone/mob.cpp b/zone/mob.cpp index b7b89d925..004eb8424 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1975,7 +1975,7 @@ void Mob::SetAttackTimer() { continue; if(pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == bagTypeQuiver) { - float temp_wr = (pi->GetItem()->BagWR / 3); + float temp_wr = ( pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv) ); if(temp_wr > max_quiver) { max_quiver = temp_wr; @@ -4675,3 +4675,21 @@ FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { } } +//DCBOOKMARK +bool Mob::HasSpellEffect(int effectid) +{ + int i; + + uint32 buff_count = GetMaxTotalSlots(); + for(i = 0; i < buff_count; i++) + { + if(buffs[i].spellid == SPELL_UNKNOWN) { continue; } + + if(IsEffectInSpell(buffs[i].spellid, effectid)) + { + return(1); + } + } + return(0); +} + diff --git a/zone/mob.h b/zone/mob.h index cefa8842d..2dab86463 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -789,6 +789,31 @@ public: inline void SetEmoteID(uint16 emote) { emoteid = emote; } inline uint16 GetEmoteID() { return emoteid; } + //DCBOOKMARK + bool HasSpellEffect(int effectid); + int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster); + float mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker); + float mod_riposte_chance(float ripostchance, Mob* attacker); + float mod_block_chance(float blockchance, Mob* attacker); + float mod_parry_chance(float parrychance, Mob* attacker); + float mod_dodge_chance(float dodgechance, Mob* attacker); + float mod_monk_weight(float monkweight, Mob* attacker); + float mod_mitigation_rating(float mitigation_rating, Mob* attacker); + float mod_attack_rating(float attack_rating, Mob* defender); + int32 mod_kick_damage(int32 dmg); + int32 mod_bash_damage(int32 dmg); + int32 mod_frenzy_damage(int32 dmg); + int32 mod_monk_special_damage(int32 ndamage, SkillType skill_type); + int32 mod_backstab_damage(int32 ndamage); + int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); + uint32 mod_archery_bonus_damage(uint32 MaxDmg); + int32 mod_archery_damage(int32 TotalDmg, bool hasbonus); + uint16 mod_throwing_damage(uint16 MaxDmg); + int32 mod_cast_time(int32 cast_time); + int mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id); + int mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2); + int mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster); + protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp new file mode 100644 index 000000000..af228ed9e --- /dev/null +++ b/zone/mod_functions.cpp @@ -0,0 +1,72 @@ +#include "../common/debug.h" +#include "../common/timer.h" +#include +#include +#include "spawn2.h" +#include "entity.h" +#include "masterentity.h" +#include "zone.h" +#include "spawngroup.h" +#include "zonedb.h" +#include "npc.h" +#include "mob.h" +#include "client.h" +#include "worldserver.h" +#include "QuestParserCollection.h" +#include +#include + +extern EntityList entity_list; +extern Zone* zone; + +extern WorldServer worldserver; + +using namespace std; + +void Zone::mod_init() { return; } +void Zone::mod_repop() { return; } + +void NPC::mod_prespawn(Spawn2 *sp) { return; } +int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } +void NPC::mod_npc_killed_merit(Mob* c) { return; } +void NPC::mod_npc_killed(Mob* oos) { return; } + +int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } +bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } //Potentially dangerous string handling here +bool Client::mod_can_increase_skill(SkillType skillid, Mob* against_who) { return(false); } +int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } +int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } +int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } +int Client::mod_client_haste(int h) { return(h); } +void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } +bool Client::mod_saylink(const std::string&, bool silentsaylink) { return(true); } +int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } +float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } +float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } +int32 Client::mod_tribute_item_value(int32 pts) { return(pts); } +void Client::mod_client_death_npc(Mob* killerMob) { return; } +void Client::mod_client_death_duel(Mob* killerMob) { return; } +void Client::mod_client_death_env() { return; } + +int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } +float Mob::mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker) { return(chancetohit); } +float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } +float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } +float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } +float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } +float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } +float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } +float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } +int32 Mob::mod_kick_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_bash_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_frenzy_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_monk_special_damage(int32 ndamage, SkillType skill_type) { return(ndamage); } +int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } +int Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } +uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg) { return(MaxDmg); } +int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus) { return(TotalDmg); } +uint16 Mob::mod_throwing_damage(uint16 MaxDmg) { return(MaxDmg); } +int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } +int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } +int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } +int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { return(resist_chance + level_mod + resist_modifier + target_resist); } diff --git a/zone/mod_functions_base.cpp b/zone/mod_functions_base.cpp new file mode 100644 index 000000000..af228ed9e --- /dev/null +++ b/zone/mod_functions_base.cpp @@ -0,0 +1,72 @@ +#include "../common/debug.h" +#include "../common/timer.h" +#include +#include +#include "spawn2.h" +#include "entity.h" +#include "masterentity.h" +#include "zone.h" +#include "spawngroup.h" +#include "zonedb.h" +#include "npc.h" +#include "mob.h" +#include "client.h" +#include "worldserver.h" +#include "QuestParserCollection.h" +#include +#include + +extern EntityList entity_list; +extern Zone* zone; + +extern WorldServer worldserver; + +using namespace std; + +void Zone::mod_init() { return; } +void Zone::mod_repop() { return; } + +void NPC::mod_prespawn(Spawn2 *sp) { return; } +int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } +void NPC::mod_npc_killed_merit(Mob* c) { return; } +void NPC::mod_npc_killed(Mob* oos) { return; } + +int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } +bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } //Potentially dangerous string handling here +bool Client::mod_can_increase_skill(SkillType skillid, Mob* against_who) { return(false); } +int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } +int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } +int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } +int Client::mod_client_haste(int h) { return(h); } +void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } +bool Client::mod_saylink(const std::string&, bool silentsaylink) { return(true); } +int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } +float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } +float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } +int32 Client::mod_tribute_item_value(int32 pts) { return(pts); } +void Client::mod_client_death_npc(Mob* killerMob) { return; } +void Client::mod_client_death_duel(Mob* killerMob) { return; } +void Client::mod_client_death_env() { return; } + +int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } +float Mob::mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker) { return(chancetohit); } +float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } +float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } +float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } +float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } +float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } +float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } +float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } +int32 Mob::mod_kick_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_bash_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_frenzy_damage(int32 dmg) { return(dmg); } +int32 Mob::mod_monk_special_damage(int32 ndamage, SkillType skill_type) { return(ndamage); } +int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } +int Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } +uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg) { return(MaxDmg); } +int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus) { return(TotalDmg); } +uint16 Mob::mod_throwing_damage(uint16 MaxDmg) { return(MaxDmg); } +int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } +int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } +int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } +int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { return(resist_chance + level_mod + resist_modifier + target_resist); } diff --git a/zone/npc.cpp b/zone/npc.cpp index a2c1addb1..8f39ea78d 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1895,7 +1895,8 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) if(id == "special_attacks") { - NPCSpecialAttacks(val.c_str(), 0); + //DCBOOKMARK - Added reset flag. + NPCSpecialAttacks(val.c_str(), 0, 1); return; } @@ -2414,3 +2415,74 @@ FACTION_VALUE NPC::CheckNPCFactionAlly(int32 other_faction) { bool NPC::IsFactionListAlly(uint32 other_faction) { return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); } + +//DCBOOKMARK +int NPC::GetScore() +{ + int lv = min(70, (int)GetLevel()); + int basedmg = (lv*2)*(1+(lv / 100)) - (lv / 2); + int minx = 0; + int basehp = 0; + int hpcontrib = 0; + int dmgcontrib = 0; + int spccontrib = 0; + int hp = GetMaxHP(); + int mindmg = min_dmg; + int maxdmg = max_dmg; + int final; + + if(lv < 46) + { + minx = ceil( ((lv - (lv / 10)) - 1) ); + basehp = (lv * 10) + (lv * lv); + } + else + { + minx = ceil( ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); + basehp = (lv * 10) + ((lv * lv) * 4); + } + + if(hp > basehp) + { + hpcontrib = (int)( (float)((float)hp / (float)basehp) * 1.5); + if(hpcontrib > 5) { hpcontrib = 5; } + + if(maxdmg > basedmg) + { + dmgcontrib = ceil( ((maxdmg / basedmg) * 1.5) ); + } + + if(HasNPCSpecialAtk("E")) { spccontrib++; } //Enrage + if(HasNPCSpecialAtk("F")) { spccontrib++; } //Flurry + if(HasNPCSpecialAtk("R")) { spccontrib++; } //Rampage + if(HasNPCSpecialAtk("r")) { spccontrib++; } //Area Rampage + if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon + if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple + if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad + if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //Unslowable + if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield + } + + if(npc_spells_id > 12) + { + if(lv < 16) { spccontrib++; } + else { spccontrib += (int)floor(lv/15); } + } + + final = minx + hpcontrib + dmgcontrib + spccontrib; + final = max(1, final); + final = min(100, final); + return(final); +} + +uint32 NPC::GetSpawnKillCount() +{ + uint32 sid = GetSpawnPointID(); + + if(sid > 0) + { + return(zone->GetSpawnKillCount(sid)); + } + + return(0); +} diff --git a/zone/npc.h b/zone/npc.h index e810cfe1f..f72c10d41 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -154,7 +154,7 @@ public: void AddItem(const Item_Struct* item, uint16 charges, bool equipitem = true); void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); void AddLootTable(); - + void AddLootTable(uint32 ldid); void DescribeAggro(Client *towho, Mob *mob, bool verbose); void RemoveItem(uint32 item_id, uint16 quantity = 0, uint16 slot = 0); void CheckMinMaxLevel(Mob *them); @@ -454,6 +454,14 @@ public: void PrintOutQuestItems(Client* c); + //DCBOOKMARK + uint32 GetSpawnKillCount(); + int GetScore(); + void mod_prespawn(Spawn2 *sp); + int mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other); + void mod_npc_killed_merit(Mob* c); + void mod_npc_killed(Mob* oos); + protected: const NPCType* NPCTypedata; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index de6632f78..aa5de794c 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5651,6 +5651,91 @@ XS(XS_Client_GetInstanceID) XSRETURN(1); } +XS(XS_Client_HasSpellScribed); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_HasSpellScribed) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::HasSpellScribed(THIS, spell_id)"); + { + Client * THIS; + bool RETVAL; + int spell_id = (int)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->HasSpellScribed(spell_id); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_Client_SetAccountFlag); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_SetAccountFlag) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: Client::SetAccountFlag(THIS, flag, value)"); + { + Client * THIS; + //char* flag = (char *)SvPV_nolen(ST(1)); + //char* value = (char *)SvTRUE(ST(2)); + + std::string flag( (char *)SvPV_nolen(ST(1)) ); + std::string value( (char *)SvTRUE(ST(2)) ); + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->SetAccountFlag(flag, value); + } + XSRETURN_EMPTY; +} + +XS(XS_Client_GetAccountFlag); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetAccountFlag) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::GetAccountFlag(THIS, flag)"); + { + Client * THIS; + //char* flag = (char *)SvPV_nolen(ST(1)); + //char* value = (char *)SvTRUE(ST(2)); + + std::string flag( (char *)SvPV_nolen(ST(1)) ); + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + std::string value = THIS->GetAccountFlag(flag); + + sv_setpv(TARG, value.c_str()); XSprePUSH; PUSHTARG; + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -5877,6 +5962,9 @@ XS(boot_Client) newXSproto(strcpy(buf, "AddAlternateCurrencyValue"), XS_Client_AddAlternateCurrencyValue, file, "$$$"); newXSproto(strcpy(buf, "SendWebLink"), XS_Client_SendWebLink, file, "$:$"); newXSproto(strcpy(buf, "GetInstanceID"), XS_Client_GetInstanceID, file, "$$"); + newXSproto(strcpy(buf, "HasSpellScribed"), XS_Client_HasSkill, file, "$$"); + newXSproto(strcpy(buf, "SetAccountFlag"), XS_Client_SetAccountFlag, file, "$$"); + newXSproto(strcpy(buf, "GetAccountFlag"), XS_Client_GetAccountFlag, file, "$$"); XSRETURN_YES; } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 94d09ed16..ca6975b99 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3909,8 +3909,8 @@ XS(XS_Mob_CastSpell); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_CastSpell) { dXSARGS; - if (items < 3 || items > 6) - Perl_croak(aTHX_ "Usage: Mob::CastSpell(THIS, spell_id, target_id, slot= 10, casttime= -1, mana_cost= -1)"); + if (items < 3 || items > 7) + Perl_croak(aTHX_ "Usage: Mob::CastSpell(THIS, spell_id, target_id, slot= 10, casttime= -1, mana_cost= -1, resist_adjust = 0)"); { Mob * THIS; uint16 spell_id = (uint16)SvUV(ST(1)); @@ -3918,6 +3918,7 @@ XS(XS_Mob_CastSpell) uint16 slot; int32 casttime; int32 mana_cost; + int16 resist_adjust; if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -3946,7 +3947,16 @@ XS(XS_Mob_CastSpell) mana_cost = (int32)SvIV(ST(5)); } - THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost); + if(items < 7) + { + resist_adjust = 0; + } + else + { + resist_adjust = (int16)SvIV(ST(6)); + } + + THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, &resist_adjust); } XSRETURN_EMPTY; } @@ -3955,13 +3965,14 @@ XS(XS_Mob_SpellFinished); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_SpellFinished) { dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: Mob::SpellFinished(spell_id, spell_target = this, mana_cost = 0)"); + if (items < 2 || items > 5) + Perl_croak(aTHX_ "Usage: Mob::SpellFinished(spell_id, spell_target = this, mana_cost = 0, resist_diff = 0)"); { Mob * THIS; uint16 spell_id = (uint16)SvUV(ST(1)); Mob * spell_target; uint16 mana_cost = 0; + int16 resist_diff; if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -3990,7 +4001,16 @@ XS(XS_Mob_SpellFinished) if (items > 3) mana_cost = (uint16)SvUV(ST(3)); - THIS->SpellFinished(spell_id, spell_target, 10, mana_cost, -1, spells[spell_id].ResistDiff); + if (items > 4) + { + resist_diff = (int16)SvUV(ST(4)); + } + else + { + resist_diff = spells[spell_id].ResistDiff; + } + + THIS->SpellFinished(spell_id, spell_target, 10, mana_cost, -1, resist_diff); } XSRETURN_EMPTY; } @@ -8352,4 +8372,4 @@ XS(boot_Mob) XSRETURN_YES; } -#endif //EMBPERL_XS_CLASSES \ No newline at end of file +#endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index fc0177cd4..bb025d324 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -143,7 +143,17 @@ XS(XS_NPC_AddLootTable) if(THIS == NULL) Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - THIS->AddLootTable(); + uint32 loottable_id = 0; + + if(items > 1) + { + loottable_id = (uint32)SvUV(ST(1)); + THIS->AddLootTable(loottable_id); + } + else + { + THIS->AddLootTable(); + } } XSRETURN_EMPTY; } @@ -2075,6 +2085,57 @@ XS(XS_NPC_GetAccuracyRating) XSRETURN(1); } +XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnKillCount) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnKillCount(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->GetSpawnKillCount(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetScore); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetScore) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetScore(THIS)"); + { + NPC * THIS; + int RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->GetScore(); + XSprePUSH; PUSHi((UV)RETVAL); + } + XSRETURN(1); +} #ifdef __cplusplus extern "C" @@ -2174,6 +2235,8 @@ XS(boot_NPC) newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetAttackSpeed, file, "$"); newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetSlowMitigation, file, "$"); newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); + newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); + newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetSpawnKillCount, file, "$"); XSRETURN_YES; } diff --git a/zone/perlparser.cpp b/zone/perlparser.cpp index 871551b10..367b202e0 100644 --- a/zone/perlparser.cpp +++ b/zone/perlparser.cpp @@ -3500,6 +3500,38 @@ XS(XS__crosszonemessageplayerbyname) XSRETURN_EMPTY; } +XS(XS__GetSpellName); +XS(XS__GetSpellName) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: GetSpellName(spell_id)"); + + int32 spell_id = (int32)SvUV(ST(0)); + dXSTARG; + + Const_char * RETVAL = GetSpellName(spell_id); + + sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; + XSRETURN(1); +} + +XS(XS__GetMana); +XS(XS__GetMana) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: GetMana(spell_id)"); + + uint32 spell_id = (uint32)SvIV(ST(0)); + + uint16 manacost = 0; + dXSTARG; + + manacost = quest_manager.GetMana(spell_id); + XSRETURN_UV(manacost); +} + /* This is the callback perl will look for to setup the quest package's XSUBs @@ -3722,6 +3754,8 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file); + newXS(strcpy(buf, "GetSpellName"), XS__GetSpellName, file); + newXS(strcpy(buf, "GetMana"), XS__GetMana, file); XSRETURN_YES; } diff --git a/zone/pets.cpp b/zone/pets.cpp index 531704588..875fa5c71 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -232,8 +232,11 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, c int16 act_power = 0; // The actual pet power we'll use. if (petpower == -1) { - if (this->IsClient()) + if (this->IsClient()) { act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); + //DCBOOKMARK + act_power = CastToClient()->mod_pet_power(act_power, spell_id); + } } else if (petpower > 0) act_power = petpower; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index b93a3102f..43cfdc529 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -830,10 +830,11 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { { if ( - spells[curspell].classes[WARRIOR] != 0 && //check if spell exists - spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level - spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level - spells[curspell].skill != 52 + spells[curspell].classes[WARRIOR] != 0 && //check if spell exists + spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level + spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level + spells[curspell].skill != 52 && + ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) //DCBOOKMARK ) { if (book_slot == -1) //no more book slots @@ -872,7 +873,8 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { spells[curspell].classes[WARRIOR] != 0 && //check if spell exists spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level - spells[curspell].skill != 52 + spells[curspell].skill != 52 && + ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) //DCBOOKMARK ) { if(IsDiscipline(curspell)){ diff --git a/zone/questmgr.h b/zone/questmgr.h index 96174abc6..ee7ba6050 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -257,6 +257,8 @@ public: bool createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender); #endif + inline uint16 GetMana(uint32 spell_id) { return( spells[spell_id].mana); } + protected: Mob *owner; //NPC is never NULL when functions are called. Client *initiator; //this can be null. diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index e08bc572a..b441bc683 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -68,7 +68,7 @@ Spawn2::Spawn2(uint32 in_spawn2_id, uint32 spawngroup_id, float in_x, float in_y, float in_z, float in_heading, uint32 respawn, uint32 variance, uint32 timeleft, uint32 grid, uint16 in_cond_id, int16 in_min_value, bool in_enabled, EmuAppearance anim) -: timer(100000) +: timer(100000), killcount(0) { spawn2_id = in_spawn2_id; spawngroup_id_ = spawngroup_id; @@ -219,6 +219,10 @@ bool Spawn2::Process() { currentnpcid = npcid; NPC* npc = new NPC(tmp, this, x, y, z, heading, FlyMode3); + + //DCBOOKMARK + npc->mod_prespawn(this); + npcthis = npc; npc->AddLootTable(); npc->SetSp2(spawngroup_id_); @@ -328,7 +332,7 @@ void Spawn2::ForceDespawn() } //resets our spawn as if we just died -void Spawn2::DeathReset() +void Spawn2::DeathReset(bool realdeath) { //get our reset based on variance etc and store it locally uint32 cur = resetTimer(); @@ -338,6 +342,9 @@ void Spawn2::DeathReset() //zero out our NPC since he is now gone npcthis = NULL; + //DCBOOKMARK + if(realdeath) { killcount++; } + //if we have a valid spawn id if(spawn2_id) { diff --git a/zone/spawn2.h b/zone/spawn2.h index 4956e13d0..c353f4be4 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -49,7 +49,7 @@ public: void Repop(uint32 delay = 0); void ForceDespawn(); - void DeathReset(); //resets the spawn in the case the npc dies, also updates db if needed + void DeathReset(bool realdeath = 0); //resets the spawn in the case the npc dies, also updates db if needed void SpawnConditionChanged(const SpawnCondition &c, int16 old_value); uint32 GetID() { return spawn2_id; } @@ -71,6 +71,8 @@ public: bool NPCPointerValid() { return (npcthis!=NULL); } void SetNPCPointer(NPC* n) { npcthis = n; } void SetTimer(uint32 duration) { timer.Start(duration); } + //DCBOOKMARK + uint32 GetKillCount() { return killcount; } protected: friend class Zone; Timer timer; @@ -92,6 +94,8 @@ private: bool enabled; EmuAppearance anim; bool IsDespawned; + //DCBOOKMARK + uint32 killcount; }; class SpawnCondition { diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1560e5592..419aeb6dd 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -48,6 +48,9 @@ int Mob::GetKickDamage() { int32 mindmg = 1; ApplySpecialAttackMod(KICK, dmg,mindmg); + //DCBOOKMARK + dmg = mod_kick_damage(dmg); + return(dmg); } @@ -67,6 +70,9 @@ int Mob::GetBashDamage() { int32 mindmg = 1; ApplySpecialAttackMod(BASH, dmg, mindmg); + //DCBOOKMARK + dmg = mod_bash_damage(dmg); + return(dmg); } @@ -281,6 +287,9 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int32 min_dmg = 0; DoAnim(anim2HSlashing); + //DCBOOKMARK + max_dmg = mod_frenzy_damage(max_dmg); + if (GetLevel() < 51) min_dmg = 1; else @@ -490,7 +499,10 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) ht = max_dmg; } } - + + //DCBOOKMARK -- This can potentially stack with changes to kick damage + ht = ndamage = mod_monk_special_damage(ndamage, skill_type); + DoSpecialAttackDamage(other, skill_type, ndamage, min_dmg, ht, reuse); return(reuse); @@ -663,6 +675,9 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) ndamage = -5; } + //DCBOOKMARK + ndamage = mod_backstab_damage(ndamage); + DoSpecialAttackDamage(other, BACKSTAB, ndamage, min_hit, hate, ReuseTime); DoAnim(animPiercing); } @@ -879,22 +894,35 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item mlog(COMBAT__RANGED, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); + bool dobonus = false; if(GetClass() == RANGER && GetLevel() > 50) { - if(RuleB(Combat, ArcheryBonusRequiresStationary)) + //DCBOOKMARK + int bonuschance = RuleI(Combat, ArcheryBonusChance); + + bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); + + if( !RuleB(Combat, UseArcheryBonusRoll) || (MakeRandomInt(1, 100) < bonuschance) ) { - if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) + if(RuleB(Combat, ArcheryBonusRequiresStationary)) { - MaxDmg *= (float)2; - hate *= (float)2; - mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); - Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); + if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) + { + dobonus = true; + } + } + else + { + dobonus = true; } } - else + + if(dobonus) { MaxDmg *= (float)2; hate *= (float)2; + MaxDmg = mod_archery_bonus_damage(MaxDmg); + mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); } @@ -925,6 +953,10 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item ApplyMeleeDamageBonus(ARCHERY, TotalDmg); TotalDmg += other->GetAdditionalDamage(this, 0, true, ARCHERY); TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(ARCHERY) / 100) + GetSkillDmgAmt(ARCHERY); + + //DCBOOKMARK + TotalDmg = mod_archery_damage(TotalDmg, dobonus); + TryCriticalHit(other, ARCHERY, TotalDmg); other->AddToHateList(this, hate, 0, false); } @@ -941,6 +973,12 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item { TryWeaponProc(RangeWeapon, other, 11); } + + //DCBOOKMARK - Arrow procs because why not? + if((Ammo != NULL) && GetTarget() && other && (other->GetHP() > -10)) + { + TryWeaponProc(Ammo, other, 11); + } } void NPC::RangedAttack(Mob* other) @@ -1088,6 +1126,9 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) if(MaxDmg < minDmg) MaxDmg = minDmg; + //DCBOOKMARK + MaxDmg = mod_throwing_damage(MaxDmg); + return MaxDmg; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4c7d4cb98..94181b238 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -627,7 +627,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif // EverHood if(caster && GetPrimaryFaction()>0) { - caster->AddFactionBonus(GetPrimaryFaction(),spell.base[0]); + caster->AddFactionBonus(GetPrimaryFaction(),effect_value); } break; } @@ -1178,7 +1178,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) { Gate(); } - // shadow step is handled by client already, nothing required + // solar: shadow step is handled by client already, nothing required break; } @@ -1189,7 +1189,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif if (spells[spell_id].base[i] == 1) BuffFadeByEffect(SE_Blind); - // handled by client + // solar: handled by client // TODO: blind flag? break; } @@ -1369,7 +1369,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Spin: %d", effect_value); #endif - // the spinning is handled by the client + // solar: the spinning is handled by the client int max_level = spells[spell_id].max[i]; if(max_level == 0) max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit @@ -1383,7 +1383,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) } else { - // the spinning is handled by the client + // solar: the spinning is handled by the client // Stun duration is based on the effect_value, not the buff duration(alot don't have buffs) Stun(effect_value); if(!IsClient()) { @@ -2004,7 +2004,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Call Pet"); #endif - // this is cast on self, not on the pet + // solar: this is cast on self, not on the pet if(GetPet() && GetPet()->IsNPC()) { GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading()); @@ -2015,7 +2015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_StackingCommand_Block: case SE_StackingCommand_Overwrite: { - // these are special effects used by the buff stuff + // solar: these are special effects used by the buff stuff break; } @@ -2100,7 +2100,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Skill Attack"); #endif - /* + /*Kayen: Weapon Damage = spells[spell_id].base[i] Chance to Hit Bonus = spells[spell_id].base2[i] ???? = spells[spell_id].max[i] - MOST of the effects have this value. @@ -2809,13 +2809,17 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, mlog(SPELLS__BARDS, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value); } + //DCBOOKMARK + effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster); + return(effect_value); } -// generic formula calculations +// solar: generic formula calculations int Mob::CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining) { /* +neotokyo: i need those formulas checked!!!! 0 = base 1 - 99 = base + level * formulaID @@ -2844,11 +2848,8 @@ int Mob::CalcSpellEffectValue_formula(int formula, int base, int max, int caster int result = 0, updownsign = 1, ubase = base; if(ubase < 0) ubase = 0 - ubase; - int level_diff = caster_level - GetMinLevel(spell_id); - if (level_diff < 0) - level_diff = 0; - // this updown thing might look messed up but if you look at the + // solar: this updown thing might look messed up but if you look at the // spells it actually looks like some have a positive base and max where // the max is actually less than the base, hence they grow downward /* @@ -2877,17 +2878,17 @@ snare has both of them negative, yet their range should work the same: case 70: result = ubase/100; break; case 0: - case 100: // confirmed 2/6/04 + case 100: // solar: confirmed 2/6/04 result = ubase; break; - case 101: // confirmed 2/6/04 + case 101: // solar: confirmed 2/6/04 result = updownsign * (ubase + (caster_level / 2)); break; - case 102: // confirmed 2/6/04 + case 102: // solar: confirmed 2/6/04 result = updownsign * (ubase + caster_level); break; - case 103: // confirmed 2/6/04 + case 103: // solar: confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 2)); break; - case 104: // confirmed 2/6/04 + case 104: // solar: confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 3)); break; - case 105: // confirmed 2/6/04 + case 105: // solar: confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 4)); break; case 107: @@ -2895,35 +2896,35 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase + (caster_level / 2)); break; case 108: result = updownsign * (ubase + (caster_level / 3)); break; - case 109: // confirmed 2/6/04 + case 109: // solar: confirmed 2/6/04 result = updownsign * (ubase + (caster_level / 4)); break; - case 110: // confirmed 2/6/04 + case 110: // solar: confirmed 2/6/04 //is there a reason we dont use updownsign here??? result = ubase + (caster_level / 5); break; case 111: - result = updownsign * (ubase + 6 * level_diff); break; + result = updownsign * (ubase + 6 * (caster_level - GetMinLevel(spell_id))); break; case 112: - result = updownsign * (ubase + 8 * level_diff); break; + result = updownsign * (ubase + 8 * (caster_level - GetMinLevel(spell_id))); break; case 113: - result = updownsign * (ubase + 10 * level_diff); break; + result = updownsign * (ubase + 10 * (caster_level - GetMinLevel(spell_id))); break; case 114: - result = updownsign * (ubase + 15 * level_diff); break; + result = updownsign * (ubase + 15 * (caster_level - GetMinLevel(spell_id))); break; //these formula were updated according to lucy 10/16/04 - case 115: // this is only in symbol of transal - result = ubase + 6 * level_diff; break; - case 116: // this is only in symbol of ryltan - result = ubase + 8 * level_diff; break; - case 117: // this is only in symbol of pinzarn - result = ubase + 12 * level_diff; break; - case 118: // used in naltron and a few others - result = ubase + 20 * level_diff; break; + case 115: // solar: this is only in symbol of transal + result = ubase + 6 * (caster_level - GetMinLevel(spell_id)); break; + case 116: // solar: this is only in symbol of ryltan + result = ubase + 8 * (caster_level - GetMinLevel(spell_id)); break; + case 117: // solar: this is only in symbol of pinzarn + result = ubase + 12 * (caster_level - GetMinLevel(spell_id)); break; + case 118: // solar: used in naltron and a few others + result = ubase + 20 * (caster_level - GetMinLevel(spell_id)); break; - case 119: // confirmed 2/6/04 + case 119: // solar: confirmed 2/6/04 result = ubase + (caster_level / 8); break; - case 121: // corrected 2/6/04 + case 121: // solar: corrected 2/6/04 result = ubase + (caster_level / 3); break; case 122: { @@ -2935,7 +2936,7 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase - (12 * ticdif)); break; } - case 123: // added 2/6/04 + case 123: // solar: added 2/6/04 result = MakeRandomInt(ubase, abs(max)); break; @@ -3306,7 +3307,7 @@ void Mob::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, M } } -// removes the buff in the buff slot 'slot' +// solar: removes the buff in the buff slot 'slot' void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { if(slot < 0 || slot > GetMaxTotalSlots()) @@ -5319,7 +5320,7 @@ int32 Mob::GetAdditionalDamage(Mob *caster, uint32 spell_id, bool use_skill, uin int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) { - //9-17-12: This is likely causing crashes, disabled till can resolve. + //Kayen 9-17-12: This is likely causing crashes, disabled till can resolve. if (IsBard) return value; diff --git a/zone/spells.cpp b/zone/spells.cpp index 6ff8bb3b8..9a9a19f60 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -440,6 +440,9 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(true); } + //DCBOOKMARK + cast_time = mod_cast_time(cast_time); + // ok we know it has a cast time so we can start the timer now spellend_timer.Start(cast_time); @@ -1099,11 +1102,53 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT)) && inventory_slot != 0xFFFFFFFF) // 10 is an item { - const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - if (inst && inst->IsType(ItemClassCommon) && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges()) + bool fromaug = false; + const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; + Item_Struct* augitem = 0; + uint32 recastdelay = 0; + uint32 recasttype = 0; + + for(int r = 0; r < MAX_AUGMENT_SLOTS; r++) { + const ItemInst* aug_i = inst->GetAugment(r); + + if(!aug_i) + continue; + const Item_Struct* aug = aug_i->GetItem(); + if(!aug) + continue; + + if ( aug->Click.Effect == spell_id ) + { + recastdelay = aug_i->GetItem()->RecastDelay; + recasttype = aug_i->GetItem()->RecastType; + fromaug = true; + break; + } + } + + //Test the aug recast delay + if(IsClient() && fromaug && recastdelay > 0) + { + if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recasttype), false)) { + Message_StringID(13, SPELL_RECAST); + mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: item spell reuse timer not expired", spell_id); + InterruptSpell(); + return; + } + else + { + //Can we start the timer here? I don't see why not. + CastToClient()->GetPTimers().Start((pTimerItemStart + recasttype), recastdelay); + } + } + + if (inst && inst->IsType(ItemClassCommon) && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { //const Item_Struct* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; + + if(fromaug) { charges = -1; } //Don't destroy the parent item + if(charges > -1) { // charged item, expend a charge mlog(SPELLS__CASTING, "Spell %d: Consuming a charge from item %s (%d) which had %d/%d charges.", spell_id, inst->GetItem()->Name, inst->GetItem()->ID, inst->GetCharges(), inst->GetItem()->MaxCharges); DeleteChargeFromSlot = inventory_slot; @@ -2328,6 +2373,9 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste IsBlindSpell(spell_id)) res += 1; + //DCBOOKMARK + res = mod_buff_duration(res, caster, target, spell_id); + mlog(SPELLS__CASTING, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d", spell_id, castlevel, formula, duration, res); @@ -2431,6 +2479,10 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return -1; } + //DCBOOKMARK + int modval = mod_spell_stack(spellid1, caster_level1, caster1, spellid2, caster_level2, caster2); + if(modval < 2) { return(modval); } + //resurrection effects wont count for overwrite/block stacking switch(spellid1) { @@ -4019,40 +4071,67 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use resist_chance = 0; } - //Adjust our resist chance based on level modifiers - int temp_level_diff = GetLevel() - caster->GetLevel(); - if(IsNPC() && GetLevel() >= RuleI(Casting, ResistFalloff)) - { - int a = (RuleI(Casting, ResistFalloff) - 1) - caster->GetLevel(); - if(a > 0) - { - temp_level_diff = a; - } - else - { - temp_level_diff = 0; - } - } + //Adjust our resist chance based on level modifiers + int temp_level_diff = GetLevel() - caster->GetLevel(); + if(IsNPC() && GetLevel() >= RuleI(Casting,ResistFalloff)) + { + int a = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + if(a > 0) + { + temp_level_diff = a; + } + else + { + temp_level_diff = 0; + } + } - if(IsClient() && GetLevel() >= 21 && temp_level_diff > 15) - { - temp_level_diff = 15; - } + if(IsClient() && GetLevel() >= 21 && temp_level_diff > 15) + { + temp_level_diff = 15; + } - if(IsNPC() && temp_level_diff < -9) - { - temp_level_diff = -9; - } + if(IsNPC() && temp_level_diff < -9) + { + temp_level_diff = -9; + } - int level_mod = temp_level_diff * temp_level_diff / 2; - if(temp_level_diff < 0) - { - level_mod = -level_mod; - } + int level_mod = temp_level_diff * temp_level_diff / 2; + if(temp_level_diff < 0) + { + level_mod = -level_mod; + } - if(IsNPC() && (caster->GetLevel() - GetLevel()) < -20) + if(IsNPC() && (caster->GetLevel() - GetLevel()) < -20) + { + level_mod = 1000; + } + + //Even more level stuff this time dealing with damage spells + if(IsNPC() && IsDamageSpell(spell_id) && GetLevel() >= 17) + { + int level_diff; + if(GetLevel() >= RuleI(Casting,ResistFalloff)) + { + level_diff = (RuleI(Casting,ResistFalloff)-1) - caster->GetLevel(); + if(level_diff < 0) + { + level_diff = 0; + } + } + else + { + level_diff = GetLevel() - caster->GetLevel(); + } + level_mod += (2 * level_diff); + } + + if (CharismaCheck) { - level_mod = 1000; + //For charm chance to break checks, Default 10 CHA = -1 resist mod. + int16 cha_resist_modifier = 0; + cha_resist_modifier = caster->GetCHA()/RuleI(Spells, CharismaEffectiveness); + resist_modifier -= cha_resist_modifier; } //Add our level, resist and -spell resist modifier to our roll chance @@ -4060,32 +4139,8 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use resist_chance += resist_modifier; resist_chance += target_resist; - if (CharismaCheck) - { - //For charm chance to break checks, Default 10 CHA = -1 resist mod. - int16 cha_resist_modifier = 0; - cha_resist_modifier = caster->GetCHA()/RuleI(Spells, CharismaEffectiveness); - resist_chance -= cha_resist_modifier; - } - - //Even more level stuff this time dealing with damage spells - if(IsNPC() && IsDamageSpell(spell_id) && GetLevel() >= 17) - { - int level_diff; - if(GetLevel() >= RuleI(Casting, ResistFalloff)) - { - level_diff = (RuleI(Casting, ResistFalloff) - 1) - caster->GetLevel(); - if(level_diff < 0) - { - level_diff = 0; - } - } - else - { - level_diff = GetLevel() - caster->GetLevel(); - } - resist_chance += (2 * level_diff); - } + //DCBOOKMARK + resist_chance = mod_spell_resist(resist_chance, level_mod, resist_modifier, target_resist, resist_type, spell_id, caster); //Do our min and max resist checks. if(resist_chance > spells[spell_id].MaxResist && spells[spell_id].MaxResist != 0) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 3bcd96ca1..a5f6edcb5 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1016,6 +1016,9 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { } } + //DCBOOKMARK + chance = mod_tradeskill_chance(chance, spec); + if (((spec->tradeskill==75) || GetGM() || (chance > res)) || MakeRandomInt(0, 99) < AAChance){ success_modifier = 1; @@ -1108,6 +1111,9 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float } } + //DCBOOKMARK + chance_stage2 = mod_tradeskill_skillup(chance_stage2); + if (chance_stage2 > MakeRandomFloat(0, 99)) { //Only if stage1 and stage2 succeeded you get a skillup. SetSkill(tradeskill, current_raw_skill + 1); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index a6124d00a..e8a9ab590 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -251,6 +251,10 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { //figure out what its worth int32 pts = inst->GetItem()->Favor; + + //DCBOOKMARK + pts = mod_tribute_item_value(pts); + if(pts < 1) { Message(13, "This item is worthless for favor."); return(0); diff --git a/zone/zone.cpp b/zone/zone.cpp index aa58d1bd9..9eb88b172 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -917,7 +917,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) autoshutdown_timer((RuleI(Zone, AutoShutdownDelay))), clientauth_timer(AUTHENTICATION_TIMEOUT * 1000), spawn2_timer(1000), - qglobal_purge_timer(30000) + qglobal_purge_timer(30000), + hotzone_timer(120000) { zoneid = in_zoneid; instanceid = in_instanceid; @@ -1164,6 +1165,13 @@ bool Zone::Init(bool iStaticZone) { zone->zone_time.setEQTimeZone(database.GetZoneTZ(zoneid, GetInstanceVersion())); LogFile->write(EQEMuLog::Status, "Init Finished: ZoneID = %d, Time Offset = %d", zoneid, zone->zone_time.getEQTimeZone()); + + //DCBOOKMARK + LoadTickItems(); + + //MODDING HOOK FOR ZONE INIT + mod_init(); + return true; } @@ -1483,6 +1491,9 @@ bool Zone::Process() { } } + //DCBOOKMARK + if(hotzone_timer.Check()) { UpdateHotzone(); } + return true; } @@ -1531,6 +1542,9 @@ void Zone::Repop(uint32 delay) { MZoneLock.unlock(); initgrids_timer.Start(); + + //MODDING HOOK FOR REPOP + mod_repop(); } void Zone::GetTimeSync() @@ -2657,3 +2671,75 @@ void Zone::ReloadWorld(uint32 Option){ parse->ReloadQuests(); } } + +//DCBOOKMARK +void Zone::LoadTickItems() +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + tick_items.clear(); + //tick_globals.clear(); + + if(database.RunQuery(query, MakeAnyLenString(&query, "SELECT it_itemid, it_chance, it_level, it_qglobal, it_bagslot FROM item_tick"), errbuf, &result)) + { + while((row = mysql_fetch_row(result))) + { + if(atoi(row[0]) < 1) + { + //tick_globals[std::string(row[0])] = { 0, atoi(row[1]), atoi(row[2]), (int16)atoi(row[4]), std::string(row[3]) }; + } + else + { + tick_items[atoi(row[0])] = { atoi(row[0]), atoi(row[1]), atoi(row[2]), (int16)atoi(row[4]), std::string(row[3]) }; + } + } + mysql_free_result(result); + safe_delete_array(query); + } + else + { + LogFile->write(EQEMuLog::Error, "Error in Zone::LoadTickItems: %s (%s)", query, errbuf); + safe_delete_array(query); + } +} + +uint32 Zone::GetSpawnKillCount(uint32 in_spawnid) { + LinkedListIterator iterator(spawn2_list); + + iterator.Reset(); + while(iterator.MoreElements()) + { + if(iterator.GetData()->GetID() == in_spawnid) + { + return(iterator.GetData()->killcount); + } + iterator.Advance(); + } +} + +void Zone::UpdateHotzone() +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + bool updh; + + if(database.RunQuery(query, MakeAnyLenString(&query,"SELECT hotzone FROM zone WHERE short_name = '%s'", GetShortName()), errbuf, &result) ) + { + if( (row = mysql_fetch_row(result)) ) + { + updh = atoi(row[0]) == 0 ? false:true; + //Hotzone status has changed + if(is_hotzone != updh) + { + is_hotzone = updh; + } + } + mysql_free_result(result); + } + safe_delete_array(query); +} diff --git a/zone/zone.h b/zone/zone.h index 8a8e2a9bf..fe32e3ef4 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -33,6 +33,7 @@ #include "tasks.h" #include "pathing.h" #include "QGlobals.h" +#include class Map; class WaterMap; @@ -69,6 +70,15 @@ struct ZoneEXPModInfo { float AAExpMod; }; +//DCBOOKMARK +struct item_tick_struct { + uint32 itemid; + uint32 chance; + uint32 level; + int16 bagslot; + std::string qglobal; +}; + extern EntityList entity_list; class database; class PathManager; @@ -253,6 +263,16 @@ public: LinkedList NPCEmoteList; + //DCBOOKMARK + void LoadTickItems(); + uint32 GetSpawnKillCount(uint32 in_spawnid); + void UpdateHotzone(); + unordered_map tick_items; + + //MODDING HOOKS + void mod_init(); + void mod_repop(); + private: uint32 zoneid; uint32 instanceid; @@ -305,6 +325,7 @@ private: LinkedList client_auth_list; QGlobalCache *qGlobals; + Timer hotzone_timer; Mutex MZoneLock; }; From f983d19e01deadbc9641c6ba937d8beeca357c4d Mon Sep 17 00:00:00 2001 From: Tabasco Date: Sun, 5 May 2013 17:53:34 -0500 Subject: [PATCH 2/9] Removed my bookmark comments and cleaned up itemtick for cases where there are no tick items. --- common/spdat.cpp | 1 - world/EQW.cpp | 1 - world/zonelist.cpp | 1 - zone/attack.cpp | 17 +---------------- zone/client.cpp | 11 ++++------- zone/client.h | 2 -- zone/client_mods.cpp | 1 - zone/client_packet.cpp | 6 +----- zone/client_process.cpp | 1 - zone/entity.cpp | 1 - zone/exp.cpp | 1 - zone/loottables.cpp | 1 - zone/mob.cpp | 1 - zone/mob.h | 1 - zone/npc.cpp | 3 +-- zone/npc.h | 1 - zone/pets.cpp | 1 - zone/questmgr.cpp | 4 ++-- zone/spawn2.cpp | 2 -- zone/spawn2.h | 2 -- zone/special_attacks.cpp | 11 ++--------- zone/spell_effects.cpp | 1 - zone/spells.cpp | 4 ---- zone/tradeskills.cpp | 2 -- zone/tribute.cpp | 1 - zone/zone.cpp | 3 --- zone/zone.h | 2 -- 27 files changed, 11 insertions(+), 72 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 3553d4866..319e94f14 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1102,7 +1102,6 @@ bool IsShortDurationBuff(uint16 spell_id) return false; } -//DCBOOKMARK const char* GetSpellName(int16 spell_id) { return( spells[spell_id].name ); diff --git a/world/EQW.cpp b/world/EQW.cpp index 0aafbdbb3..aa80e1a71 100644 --- a/world/EQW.cpp +++ b/world/EQW.cpp @@ -459,7 +459,6 @@ void EQW::ResolveBug(const char *id) { safe_delete_array(query); } -//DCBOOKMARK void EQW::SendMessage(uint32 type, const char *msg) { zoneserver_list.SendEmoteMessage(0, 0, 0, type, msg); } diff --git a/world/zonelist.cpp b/world/zonelist.cpp index c9b23a343..15451d68d 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -716,7 +716,6 @@ void ZSList::GetZoneIDList(vector &zones) { } -//DCBOOKMARK void ZSList::WorldShutDown(uint32 time, uint32 interval) { if( time > 0 ) { diff --git a/zone/attack.cpp b/zone/attack.cpp index e91fccba0..f4905ec5e 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -318,7 +318,6 @@ bool Mob::CheckHitChance(Mob* other, SkillType skillinuse, int Hand, int16 chanc if(skillinuse == ARCHERY) chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f; - //DCBOOKMARK chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); // Chance to hit; Max 95%, Min 30% @@ -399,7 +398,6 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/60.0 + (GetDEX()/200); bonus *= riposte_chance; - //DCBOOKMARK bonus = mod_riposte_chance(bonus, attacker); RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block } @@ -439,7 +437,6 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/35.0 + (GetDEX()/200); - //DCBOOKMARK bonus = mod_block_chance(bonus, attacker); RollTable[1] = RollTable[0] + (bonus * block_chance); } @@ -492,7 +489,6 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) if (!ghit) { //if they are not using a garunteed hit discipline bonus = 2.0 + skill/60.0 + (GetDEX()/200); bonus *= parry_chance; - //DCBOOKMARK bonus = mod_parry_chance(bonus, attacker); RollTable[2] = RollTable[1] + bonus; } @@ -567,7 +563,6 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) int armor = 0; float weight = 0.0; - //DCBOOKMARK float monkweight = RuleI(Combat, MonkACBonusWeight); monkweight = mod_monk_weight(monkweight, attacker); @@ -653,7 +648,6 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) } mitigation_rating *= 0.847; - //DCBOOKMARK mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); if(attacker->IsClient()) @@ -665,7 +659,6 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit) attack_rating = (attacker->GetATK() + (attacker->GetSkill(OFFENSE)*1.345) + ((attacker->GetSTR()-66) * 0.9)); } - //DCBOOKMARK attack_rating = attacker->mod_attack_rating(attack_rating, this); float d = 10.0; @@ -1246,7 +1239,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b else damage = MakeRandomInt(min_hit, max_hit); - //DCBOOKMARK damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", @@ -1487,7 +1479,6 @@ void Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ if (killerMob->IsNPC()) { parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); - //DCBOOKMARK mod_client_death_npc(killerMob); uint16 emoteid = killerMob->GetEmoteID(); @@ -1506,7 +1497,6 @@ void Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ killerMob->CastToClient()->SetDuelTarget(0); entity_list.DuelMessage(killerMob,this,false); - //DCBOOKMARK mod_client_death_duel(killerMob); } else { @@ -1880,7 +1870,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool damage = (max_dmg+eleBane); } - //DCBOOKMARK damage = mod_npc_damage(damage, skillinuse, Hand, &weapon_inst, other); int32 hate = damage; @@ -2137,7 +2126,6 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski if (kr->members[i].member != NULL) { // If Group Member is Client parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0); - //DCBOOKMARK mod_npc_killed_merit(kr->members[i].member); if(RuleB(TaskSystem, EnableTaskSystem)) @@ -2181,7 +2169,6 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski Client *c = kg->members[i]->CastToClient(); parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - //DCBOOKMARK mod_npc_killed_merit(c); if(RuleB(TaskSystem, EnableTaskSystem)) @@ -2229,7 +2216,6 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski /* Send the EVENT_KILLED_MERIT event */ parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); - //DCBOOKMARK mod_npc_killed_merit(give_exp_client); if(RuleB(TaskSystem, EnableTaskSystem)) @@ -2363,7 +2349,6 @@ void NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski Mob *oos = killerMob->GetOwnerOrSelf(); parse->EventNPC(EVENT_DEATH, this, oos, "", 0); - //DCBOOKMARK mod_npc_killed(oos); uint16 emoteid = this->GetEmoteID(); @@ -3457,7 +3442,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons if (damage > 0 && ((skill_used == BASH || skill_used == KICK) && attacker)) { // NPCs can stun with their bash/kick as soon as they recieve it. - // Clients can stun mobs under level 56 with their bash/kick when they get level 55 or greater. -- DCBOOKMARK for rules + // Clients can stun mobs under level 56 with their bash/kick when they get level 55 or greater. if( attacker->IsNPC() || (attacker->IsClient() && attacker->GetLevel() >= RuleI(Combat, ClientStunLevel) && GetLevel() < RuleI(Spells, BaseImmunityLevel)) ) { if (MakeRandomInt(0,99) < (RuleI(Character, NPCBashKickStunChance)) || attacker->IsClient()) diff --git a/zone/client.cpp b/zone/client.cpp index f2fdfb46e..357e65f30 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -326,7 +326,6 @@ Client::Client(EQStreamInterface* ieqs) } MaxXTargets = 5; XTargetAutoAddHaters = true; - //DCBOOKMARK LoadAccountFlags(); } @@ -845,7 +844,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s safe_delete(pack); } - //DCBOOKMARK - Return true to proceed, false to return + //Return true to proceed, false to return if(!mod_client_message(message, chan_num)) { return; } // Garble the message based on drunkness @@ -2343,7 +2342,7 @@ bool Client::CheckIncreaseSkill(SkillType skillid, Mob *against_who, int chancem if( against_who->SpecAttacks[IMMUNE_AGGRO] || against_who->IsClient() || GetLevelCon(against_who->GetLevel()) == CON_GREEN ) { - //DCBOOKMARK - false by default + //false by default return mod_can_increase_skill(skillid, against_who); } } @@ -2357,7 +2356,6 @@ bool Client::CheckIncreaseSkill(SkillType skillid, Mob *against_who, int chancem Chance = 1; // Make it always possible Chance = (Chance * RuleI(Character, SkillUpModifier) / 100); - //DCBOOKMARK Chance = mod_increase_skill_chance(Chance, against_who); if(MakeRandomFloat(0, 99) < Chance) @@ -2728,7 +2726,6 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ max_percent = 70 + 10 * maxHPBonus; } - //DCBOOKMARK max_percent = mod_bindwound_percent(max_percent, bindmob); int max_hp = bindmob->GetMaxHP()*max_percent/100; @@ -2750,7 +2747,6 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ bindhps += bindhps*bindBonus / 100; - //DCBOOKMARK bindhps = mod_bindwound_hp(bindhps, bindmob); //if the bind takes them above the max bindable @@ -7624,7 +7620,6 @@ some day. return 0; } -//DCBOOKMARK void Client::LoadAccountFlags() { char errbuf[MYSQL_ERRMSG_SIZE]; @@ -7675,6 +7670,8 @@ void Client::TickItemCheck() { int i; + if(zone->tick_items.empty()) { return; } + //Scan equip slots for items for(i = 0; i <= 21; i++) { diff --git a/zone/client.h b/zone/client.h index a2a9c2441..568fea9d5 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1133,7 +1133,6 @@ public: void DuplicateLoreMessage(uint32 ItemID); void GarbleMessage(char *, uint8); - //DCBOOKMARK void TickItemCheck(); void TryItemTick(int slot); int16 GetActSTR() { return( min(GetMaxSTR(), GetSTR()) ); } @@ -1466,7 +1465,6 @@ private: struct XTarget_Struct XTargets[XTARGET_HARDCAP]; - //DCBOOKMARK Timer ItemTickTimer; std::map accountflags; }; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index e9f0bef0b..4138d241b 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1415,7 +1415,6 @@ int Client::CalcHaste() { h += spellbonuses.hastetype3; h += ExtraHaste; //GM granted haste. - //DCBOOKMARK h = mod_client_haste(h); if (spellbonuses.inhibitmelee){ diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e9faaa557..ce394cd46 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2076,7 +2076,6 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } } - //DCBOOKMARK int r; bool tryaug = false; ItemInst* clickaug = 0; @@ -2147,7 +2146,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } } - else if (tryaug) //DCBOOKMARK + else if (tryaug) { if (clickaug->GetCharges() == 0) { @@ -2662,7 +2661,6 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) con->faction = FACTION_DUBIOUS; } - //DCBOOKMARK mod_consider(tmob, con); QueuePacket(outapp); @@ -3260,7 +3258,6 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) if((response).size() > 0) { - //DCBOOKMARK if( !mod_saylink(response, silentsaylink) ) { return; } if(this->GetTarget() && this->GetTarget()->IsNPC()) @@ -7778,7 +7775,6 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) if(GetHP() <= 0) { - //DCBOOKMARK mod_client_death_env(); Death(0, 32000, SPELL_UNKNOWN, HAND_TO_HAND); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 14af5edce..b07b46a0f 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -646,7 +646,6 @@ bool Client::Process() { CalcBonuses(); } - //DCBOOKMARK if(ItemTickTimer.Check()) { TickItemCheck(); diff --git a/zone/entity.cpp b/zone/entity.cpp index a9281c247..c7f7dd60a 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1888,7 +1888,6 @@ void EntityList::QueueClientsStatus(Mob* sender, const EQApplicationPacket* app, void EntityList::DuelMessage(Mob* winner, Mob* loser, bool flee) { LinkedListIterator iterator(client_list); - //DCBOOKMARK if(winner->GetLevelCon(winner->GetLevel(), loser->GetLevel()) > 2) { parse->EventPlayer(EVENT_DUEL_WIN, winner->CastToClient(), loser->GetName(), loser->CastToClient()->CharacterID()); diff --git a/zone/exp.cpp b/zone/exp.cpp index f588643bb..646d0b688 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -290,7 +290,6 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { if(check_level > maxlevel) { check_level = maxlevel; - //DCBOOKMARK if(RuleB(Character, KeepLevelOverMax)) { set_exp = GetEXPForLevel(GetLevel()+1); diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 94841d492..5ee205dba 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -376,7 +376,6 @@ void NPC::AddLootTable() { } } -//DCBOOKMARK void NPC::AddLootTable(uint32 ldid) { if (npctype_id != 0) { // check if it's a GM spawn database.AddLootTableToNPC(this,ldid, &itemlist, &copper, &silver, &gold, &platinum); diff --git a/zone/mob.cpp b/zone/mob.cpp index 004eb8424..5b672d0d3 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4675,7 +4675,6 @@ FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { } } -//DCBOOKMARK bool Mob::HasSpellEffect(int effectid) { int i; diff --git a/zone/mob.h b/zone/mob.h index 2dab86463..9940fd4d2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -789,7 +789,6 @@ public: inline void SetEmoteID(uint16 emote) { emoteid = emote; } inline uint16 GetEmoteID() { return emoteid; } - //DCBOOKMARK bool HasSpellEffect(int effectid); int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster); float mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker); diff --git a/zone/npc.cpp b/zone/npc.cpp index 8f39ea78d..3294afa02 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1895,7 +1895,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) if(id == "special_attacks") { - //DCBOOKMARK - Added reset flag. + //Added reset flag. NPCSpecialAttacks(val.c_str(), 0, 1); return; } @@ -2416,7 +2416,6 @@ bool NPC::IsFactionListAlly(uint32 other_faction) { return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); } -//DCBOOKMARK int NPC::GetScore() { int lv = min(70, (int)GetLevel()); diff --git a/zone/npc.h b/zone/npc.h index f72c10d41..df2d07394 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -454,7 +454,6 @@ public: void PrintOutQuestItems(Client* c); - //DCBOOKMARK uint32 GetSpawnKillCount(); int GetScore(); void mod_prespawn(Spawn2 *sp); diff --git a/zone/pets.cpp b/zone/pets.cpp index 875fa5c71..b6e41ecdd 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -234,7 +234,6 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, c if (petpower == -1) { if (this->IsClient()) { act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); - //DCBOOKMARK act_power = CastToClient()->mod_pet_power(act_power, spell_id); } } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 43cfdc529..fe4d63c5c 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -834,7 +834,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level spells[curspell].skill != 52 && - ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) //DCBOOKMARK + ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) ) { if (book_slot == -1) //no more book slots @@ -874,7 +874,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level spells[curspell].skill != 52 && - ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) //DCBOOKMARK + ( RuleB(Spells, UseCHAScribeHack) && spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) ) { if(IsDiscipline(curspell)){ diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index b441bc683..560f732ec 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -220,7 +220,6 @@ bool Spawn2::Process() { currentnpcid = npcid; NPC* npc = new NPC(tmp, this, x, y, z, heading, FlyMode3); - //DCBOOKMARK npc->mod_prespawn(this); npcthis = npc; @@ -342,7 +341,6 @@ void Spawn2::DeathReset(bool realdeath) //zero out our NPC since he is now gone npcthis = NULL; - //DCBOOKMARK if(realdeath) { killcount++; } //if we have a valid spawn id diff --git a/zone/spawn2.h b/zone/spawn2.h index c353f4be4..cff1ed2a9 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -71,7 +71,6 @@ public: bool NPCPointerValid() { return (npcthis!=NULL); } void SetNPCPointer(NPC* n) { npcthis = n; } void SetTimer(uint32 duration) { timer.Start(duration); } - //DCBOOKMARK uint32 GetKillCount() { return killcount; } protected: friend class Zone; @@ -94,7 +93,6 @@ private: bool enabled; EmuAppearance anim; bool IsDespawned; - //DCBOOKMARK uint32 killcount; }; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 419aeb6dd..9537bf63e 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -48,7 +48,6 @@ int Mob::GetKickDamage() { int32 mindmg = 1; ApplySpecialAttackMod(KICK, dmg,mindmg); - //DCBOOKMARK dmg = mod_kick_damage(dmg); return(dmg); @@ -70,7 +69,6 @@ int Mob::GetBashDamage() { int32 mindmg = 1; ApplySpecialAttackMod(BASH, dmg, mindmg); - //DCBOOKMARK dmg = mod_bash_damage(dmg); return(dmg); @@ -287,7 +285,6 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int32 min_dmg = 0; DoAnim(anim2HSlashing); - //DCBOOKMARK max_dmg = mod_frenzy_damage(max_dmg); if (GetLevel() < 51) @@ -500,7 +497,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) } } - //DCBOOKMARK -- This can potentially stack with changes to kick damage + //This can potentially stack with changes to kick damage ht = ndamage = mod_monk_special_damage(ndamage, skill_type); DoSpecialAttackDamage(other, skill_type, ndamage, min_dmg, ht, reuse); @@ -675,7 +672,6 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) ndamage = -5; } - //DCBOOKMARK ndamage = mod_backstab_damage(ndamage); DoSpecialAttackDamage(other, BACKSTAB, ndamage, min_hit, hate, ReuseTime); @@ -897,7 +893,6 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item bool dobonus = false; if(GetClass() == RANGER && GetLevel() > 50) { - //DCBOOKMARK int bonuschance = RuleI(Combat, ArcheryBonusChance); bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); @@ -954,7 +949,6 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item TotalDmg += other->GetAdditionalDamage(this, 0, true, ARCHERY); TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(ARCHERY) / 100) + GetSkillDmgAmt(ARCHERY); - //DCBOOKMARK TotalDmg = mod_archery_damage(TotalDmg, dobonus); TryCriticalHit(other, ARCHERY, TotalDmg); @@ -974,7 +968,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item TryWeaponProc(RangeWeapon, other, 11); } - //DCBOOKMARK - Arrow procs because why not? + //Arrow procs because why not? if((Ammo != NULL) && GetTarget() && other && (other->GetHP() > -10)) { TryWeaponProc(Ammo, other, 11); @@ -1126,7 +1120,6 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) if(MaxDmg < minDmg) MaxDmg = minDmg; - //DCBOOKMARK MaxDmg = mod_throwing_damage(MaxDmg); return MaxDmg; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 94181b238..79e5a7d3f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2809,7 +2809,6 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, mlog(SPELLS__BARDS, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value); } - //DCBOOKMARK effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster); return(effect_value); diff --git a/zone/spells.cpp b/zone/spells.cpp index 9a9a19f60..f0e3b9b7a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -440,7 +440,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(true); } - //DCBOOKMARK cast_time = mod_cast_time(cast_time); // ok we know it has a cast time so we can start the timer now @@ -2373,7 +2372,6 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste IsBlindSpell(spell_id)) res += 1; - //DCBOOKMARK res = mod_buff_duration(res, caster, target, spell_id); mlog(SPELLS__CASTING, "Spell %d: Casting level %d, formula %d, base_duration %d: result %d", @@ -2479,7 +2477,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return -1; } - //DCBOOKMARK int modval = mod_spell_stack(spellid1, caster_level1, caster1, spellid2, caster_level2, caster2); if(modval < 2) { return(modval); } @@ -4139,7 +4136,6 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use resist_chance += resist_modifier; resist_chance += target_resist; - //DCBOOKMARK resist_chance = mod_spell_resist(resist_chance, level_mod, resist_modifier, target_resist, resist_type, spell_id, caster); //Do our min and max resist checks. diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index a5f6edcb5..90f9427ef 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1016,7 +1016,6 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { } } - //DCBOOKMARK chance = mod_tradeskill_chance(chance, spec); if (((spec->tradeskill==75) || GetGM() || (chance > res)) || MakeRandomInt(0, 99) < AAChance){ @@ -1111,7 +1110,6 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float } } - //DCBOOKMARK chance_stage2 = mod_tradeskill_skillup(chance_stage2); if (chance_stage2 > MakeRandomFloat(0, 99)) { diff --git a/zone/tribute.cpp b/zone/tribute.cpp index e8a9ab590..050e191bd 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -252,7 +252,6 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { //figure out what its worth int32 pts = inst->GetItem()->Favor; - //DCBOOKMARK pts = mod_tribute_item_value(pts); if(pts < 1) { diff --git a/zone/zone.cpp b/zone/zone.cpp index 9eb88b172..a56968305 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1166,7 +1166,6 @@ bool Zone::Init(bool iStaticZone) { LogFile->write(EQEMuLog::Status, "Init Finished: ZoneID = %d, Time Offset = %d", zoneid, zone->zone_time.getEQTimeZone()); - //DCBOOKMARK LoadTickItems(); //MODDING HOOK FOR ZONE INIT @@ -1491,7 +1490,6 @@ bool Zone::Process() { } } - //DCBOOKMARK if(hotzone_timer.Check()) { UpdateHotzone(); } return true; @@ -2672,7 +2670,6 @@ void Zone::ReloadWorld(uint32 Option){ } } -//DCBOOKMARK void Zone::LoadTickItems() { char errbuf[MYSQL_ERRMSG_SIZE]; diff --git a/zone/zone.h b/zone/zone.h index fe32e3ef4..7e078dbe8 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -70,7 +70,6 @@ struct ZoneEXPModInfo { float AAExpMod; }; -//DCBOOKMARK struct item_tick_struct { uint32 itemid; uint32 chance; @@ -263,7 +262,6 @@ public: LinkedList NPCEmoteList; - //DCBOOKMARK void LoadTickItems(); uint32 GetSpawnKillCount(uint32 in_spawnid); void UpdateHotzone(); From 05d7c12d387bb1677406f10a3f09823735f0222a Mon Sep 17 00:00:00 2001 From: Tabasco Date: Sun, 5 May 2013 18:20:22 -0500 Subject: [PATCH 3/9] Various customizations from DungeonCrawl --- changelog.txt | 10 ++++++++++ ..._Account_Flags.sql => 2013_05_05_Account_Flags.sql} | 0 ...13_04_24_Item_Tick.sql => 2013_05_05_Item_Tick.sql} | 0 3 files changed, 10 insertions(+) rename utils/sql/git/required/{2013_04_24_Account_Flags.sql => 2013_05_05_Account_Flags.sql} (100%) rename utils/sql/git/required/{2013_04_24_Item_Tick.sql => 2013_05_05_Item_Tick.sql} (100%) diff --git a/changelog.txt b/changelog.txt index a77b903b0..546be96d3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,15 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/05/2013 == +Tabasco: Added EVENT_ITEM_TICK for interactive item quest scripts. (See https://github.com/josheb/quests_dc/blob/master/items/12204.pl) + Added simple account flags. Would this work better as an additional qglobal category? + Added SendMessage to EQW, useful for using CURL to broadcast to the server. + Added WorldShutDown to EQW for timed world shutdowns, also updated console worldshutdown command to optionally use timed behavior. + Added numerous modding hooks and mod_functions.cpp for easy custom formulas or future lua integration. + Added various rules for monk AC bonus weight, archery bonuses, kick/bash stuns and mob stun levels. +required SQL: 2013_05_05_Account_Flags.sql +required SQL: 2013_05_05_Item_Tick.sql + == 04/28/2013 == PiB: Implement CRC16 using CRC32. diff --git a/utils/sql/git/required/2013_04_24_Account_Flags.sql b/utils/sql/git/required/2013_05_05_Account_Flags.sql similarity index 100% rename from utils/sql/git/required/2013_04_24_Account_Flags.sql rename to utils/sql/git/required/2013_05_05_Account_Flags.sql diff --git a/utils/sql/git/required/2013_04_24_Item_Tick.sql b/utils/sql/git/required/2013_05_05_Item_Tick.sql similarity index 100% rename from utils/sql/git/required/2013_04_24_Item_Tick.sql rename to utils/sql/git/required/2013_05_05_Item_Tick.sql From a0a92587b4beec1d2d42ff78ea3853ac8ffe9301 Mon Sep 17 00:00:00 2001 From: tabasco Date: Mon, 6 May 2013 16:24:44 -0500 Subject: [PATCH 4/9] Fixing some regressions --- zone/spell_effects.cpp | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index c77630cf1..59c0b2404 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1178,7 +1178,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) { Gate(); } - // solar: shadow step is handled by client already, nothing required + // shadow step is handled by client already, nothing required break; } @@ -1189,7 +1189,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #endif if (spells[spell_id].base[i] == 1) BuffFadeByEffect(SE_Blind); - // solar: handled by client + // handled by client // TODO: blind flag? break; } @@ -1369,7 +1369,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Spin: %d", effect_value); #endif - // solar: the spinning is handled by the client + // the spinning is handled by the client int max_level = spells[spell_id].max[i]; if(max_level == 0) max_level = RuleI(Spells, BaseImmunityLevel); // Default max is 55 level limit @@ -1383,7 +1383,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) } else { - // solar: the spinning is handled by the client + // the spinning is handled by the client // Stun duration is based on the effect_value, not the buff duration(alot don't have buffs) Stun(effect_value); if(!IsClient()) { @@ -2004,7 +2004,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Call Pet"); #endif - // solar: this is cast on self, not on the pet + // this is cast on self, not on the pet if(GetPet() && GetPet()->IsNPC()) { GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading()); @@ -2015,7 +2015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_StackingCommand_Block: case SE_StackingCommand_Overwrite: { - // solar: these are special effects used by the buff stuff + // these are special effects used by the buff stuff break; } @@ -2100,7 +2100,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Skill Attack"); #endif - /*Kayen: + /* Weapon Damage = spells[spell_id].base[i] Chance to Hit Bonus = spells[spell_id].base2[i] ???? = spells[spell_id].max[i] - MOST of the effects have this value. @@ -2814,7 +2814,7 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, return(effect_value); } -// solar: generic formula calculations +// generic formula calculations int Mob::CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining) { /* @@ -2848,7 +2848,7 @@ neotokyo: i need those formulas checked!!!! if(ubase < 0) ubase = 0 - ubase; - // solar: this updown thing might look messed up but if you look at the + // this updown thing might look messed up but if you look at the // spells it actually looks like some have a positive base and max where // the max is actually less than the base, hence they grow downward /* @@ -2877,17 +2877,17 @@ snare has both of them negative, yet their range should work the same: case 70: result = ubase/100; break; case 0: - case 100: // solar: confirmed 2/6/04 + case 100: // confirmed 2/6/04 result = ubase; break; - case 101: // solar: confirmed 2/6/04 + case 101: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level / 2)); break; - case 102: // solar: confirmed 2/6/04 + case 102: // confirmed 2/6/04 result = updownsign * (ubase + caster_level); break; - case 103: // solar: confirmed 2/6/04 + case 103: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 2)); break; - case 104: // solar: confirmed 2/6/04 + case 104: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 3)); break; - case 105: // solar: confirmed 2/6/04 + case 105: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level * 4)); break; case 107: @@ -2895,10 +2895,10 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase + (caster_level / 2)); break; case 108: result = updownsign * (ubase + (caster_level / 3)); break; - case 109: // solar: confirmed 2/6/04 + case 109: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level / 4)); break; - case 110: // solar: confirmed 2/6/04 + case 110: // confirmed 2/6/04 //is there a reason we dont use updownsign here??? result = ubase + (caster_level / 5); break; @@ -2912,18 +2912,18 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase + 15 * (caster_level - GetMinLevel(spell_id))); break; //these formula were updated according to lucy 10/16/04 - case 115: // solar: this is only in symbol of transal + case 115: // this is only in symbol of transal result = ubase + 6 * (caster_level - GetMinLevel(spell_id)); break; - case 116: // solar: this is only in symbol of ryltan + case 116: // this is only in symbol of ryltan result = ubase + 8 * (caster_level - GetMinLevel(spell_id)); break; - case 117: // solar: this is only in symbol of pinzarn + case 117: // this is only in symbol of pinzarn result = ubase + 12 * (caster_level - GetMinLevel(spell_id)); break; - case 118: // solar: used in naltron and a few others + case 118: // used in naltron and a few others result = ubase + 20 * (caster_level - GetMinLevel(spell_id)); break; - case 119: // solar: confirmed 2/6/04 + case 119: // confirmed 2/6/04 result = ubase + (caster_level / 8); break; - case 121: // solar: corrected 2/6/04 + case 121: // corrected 2/6/04 result = ubase + (caster_level / 3); break; case 122: { @@ -2935,7 +2935,7 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase - (12 * ticdif)); break; } - case 123: // solar: added 2/6/04 + case 123: // added 2/6/04 result = MakeRandomInt(ubase, abs(max)); break; @@ -3306,7 +3306,7 @@ void Mob::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, M } } -// solar: removes the buff in the buff slot 'slot' +// removes the buff in the buff slot 'slot' void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { if(slot < 0 || slot > GetMaxTotalSlots()) @@ -5319,7 +5319,7 @@ int32 Mob::GetAdditionalDamage(Mob *caster, uint32 spell_id, bool use_skill, uin int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) { - //Kayen 9-17-12: This is likely causing crashes, disabled till can resolve. + // 9-17-12: This is likely causing crashes, disabled till can resolve. if (IsBard) return value; From 5cda797531393f9b5d4a0f6ab03afd59cf924e82 Mon Sep 17 00:00:00 2001 From: af4t Date: Tue, 7 May 2013 15:19:27 -0400 Subject: [PATCH 5/9] VS2010 compatibility --- zone/npc.cpp | 19 +++++++++++++++++-- zone/zone.cpp | 17 +++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index cc1aa8603..cc28aeab4 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2432,12 +2432,20 @@ int NPC::GetScore() if(lv < 46) { - minx = ceil( ((lv - (lv / 10)) - 1) ); +#if _MSC_VER==1600 + minx = ceil((float) ((lv - (lv / 10)) - 1) ); +#else + minx = ceil( ((lv - (lv / 10)) - 1) ); +#endif basehp = (lv * 10) + (lv * lv); } else { - minx = ceil( ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); +#if _MSC_VER==1600 + minx = ceil((float) ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); +#else + minx = ceil( ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); +#endif basehp = (lv * 10) + ((lv * lv) * 4); } @@ -2463,10 +2471,17 @@ int NPC::GetScore() } if(npc_spells_id > 12) +#if _MSC_VER==1600 { + if(lv < 16) { spccontrib++; } + else { spccontrib += (int)floor((float) lv/15); } + } +#else + { if(lv < 16) { spccontrib++; } else { spccontrib += (int)floor(lv/15); } } +#endif final = minx + hpcontrib + dmgcontrib + spccontrib; final = max(1, final); diff --git a/zone/zone.cpp b/zone/zone.cpp index 17271058f..028c5ef00 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -2676,7 +2676,9 @@ void Zone::LoadTickItems() char* query = 0; MYSQL_RES *result; MYSQL_ROW row; - +#if _MSC_VER==1600 + item_tick_struct ti_tmp; +#endif tick_items.clear(); //tick_globals.clear(); @@ -2689,9 +2691,20 @@ void Zone::LoadTickItems() //tick_globals[std::string(row[0])] = { 0, atoi(row[1]), atoi(row[2]), (int16)atoi(row[4]), std::string(row[3]) }; } else - { +#if _MSC_VER==1600 + { + ti_tmp.itemid = atoi(row[0]); + ti_tmp.chance = atoi(row[1]); + ti_tmp.level = atoi(row[2]); + ti_tmp.bagslot = (int16)atoi(row[4]); + ti_tmp.qglobal = std::string(row[3]); + tick_items[atoi(row[0])] = ti_tmp; + } +#else + { tick_items[atoi(row[0])] = { atoi(row[0]), atoi(row[1]), atoi(row[2]), (int16)atoi(row[4]), std::string(row[3]) }; } +#endif } mysql_free_result(result); safe_delete_array(query); From 0838d4507a2f423bde4f2ceffcc809694196bde8 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Tue, 7 May 2013 17:41:05 -0400 Subject: [PATCH 6/9] Fix NULL to nullptr for SQL queries --- zone/client_packet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d389cfcac..9724dec22 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6129,7 +6129,7 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app) " LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id=tre.recipe_id " " LEFT JOIN (SELECT recipe_id, madecount FROM char_recipe_list WHERE char_id = %u) AS crl ON tr.id=crl.recipe_id " " WHERE tr.id IN (%s) " - " AND tr.must_learn & 0x20 <> 0x20 AND ((tr.must_learn & 0x3 <> 0 AND crl.madecount IS NOT nullptr) OR (tr.must_learn & 0x3 = 0)) " + " AND tr.must_learn & 0x20 <> 0x20 AND ((tr.must_learn & 0x3 <> 0 AND crl.madecount IS NOT NULL) OR (tr.must_learn & 0x3 = 0)) " " GROUP BY tr.id " " HAVING sum(if(tre.item_id %s AND tre.iscontainer > 0,1,0)) > 0 " " LIMIT 100 ", CharacterID(), buf, containers); @@ -6184,7 +6184,7 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app) " LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id=tre.recipe_id " " LEFT JOIN (SELECT recipe_id, madecount FROM char_recipe_list WHERE char_id = %u) AS crl ON tr.id=crl.recipe_id " " WHERE %s tr.trivial >= %u AND tr.trivial <= %u " - " AND tr.must_learn & 0x20 <> 0x20 AND((tr.must_learn & 0x3 <> 0 AND crl.madecount IS NOT nullptr) OR (tr.must_learn & 0x3 = 0)) " + " AND tr.must_learn & 0x20 <> 0x20 AND((tr.must_learn & 0x3 <> 0 AND crl.madecount IS NOT NULL) OR (tr.must_learn & 0x3 = 0)) " " GROUP BY tr.id " " HAVING sum(if(tre.item_id %s AND tre.iscontainer > 0,1,0)) > 0 " " LIMIT 200 " From 059ecdb50b6373b1def84827efb09d8d45e9c7a6 Mon Sep 17 00:00:00 2001 From: Michael Cook Date: Tue, 7 May 2013 18:20:09 -0400 Subject: [PATCH 7/9] Fix NULL to nullptr for SQL queries take 2 --- common/database.cpp | 8 ++++---- zone/mob.cpp | 4 ++-- zone/questmgr.cpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c03ad97cf..8960a58e0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -428,7 +428,7 @@ bool Database::ReserveName(uint32 account_id, char* name) char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=nullptr", account_id, name), errbuf)) { + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name), errbuf)) { cerr << "Error in ReserveName query '" << query << "' " << errbuf << endl; safe_delete_array(query); return false; @@ -1196,9 +1196,9 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe { cerr << "Error in GetSafePoint query '" << query << "' " << errbuf << endl; cerr << "If it errors, run the following querys:\n"; - cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT nullptr;\n"; - cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT nullptr;\n"; - cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT nullptr DEFAULT '';\n"; + cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; + cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; + cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT NULL DEFAULT '';\n"; safe_delete_array(query); } diff --git a/zone/mob.cpp b/zone/mob.cpp index 6529a505a..6782a8826 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3784,12 +3784,12 @@ void Mob::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varna char *query = 0; char errbuf[MYSQL_ERRMSG_SIZE]; - // Make duration string either "unix_timestamp(now()) + xxx" or "nullptr" + // Make duration string either "unix_timestamp(now()) + xxx" or "NULL" stringstream duration_ss; if (duration == INT_MAX) { - duration_ss << "nullptr"; + duration_ss << "NULL"; } else { diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index bc7ac3f75..d29e99e87 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1241,11 +1241,11 @@ int QuestManager::InsertQuestGlobal( char *query = 0; char errbuf[MYSQL_ERRMSG_SIZE]; - // Make duration string either "unix_timestamp(now()) + xxx" or "nullptr" + // Make duration string either "unix_timestamp(now()) + xxx" or "NULL" stringstream duration_ss; if (duration == INT_MAX) { - duration_ss << "nullptr"; + duration_ss << "NULL"; } else { From 21a9434f89e3e5a9856024c92be9bf730ffb7d45 Mon Sep 17 00:00:00 2001 From: Derision Date: Wed, 8 May 2013 20:02:55 +0100 Subject: [PATCH 8/9] Changed dummy strings written into the TaskSelector packet from nullptr to ABCD since the packet size calculation was based on the strings being 4 characters long. --- zone/tasks.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index dcd3aad57..34b64c1db 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1158,7 +1158,7 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task if(Tasks[TaskList[i]] != nullptr) break; } - // FIXME: The 10 and 5 values in this calculation are to account for the string "nullptr" we are putting in 3 times. + // FIXME: The 10 and 5 values in this calculation are to account for the string "ABCD" we are putting in 3 times. // // Calculate how big the packet needs to be pased on the number of tasks and the // size of the variable length strings. @@ -1236,9 +1236,9 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task // FIXME: In live packets, these two strings appear to be the same as the Text1 and Text2 // strings from the first activity in the task, however the task chooser/selector // does not appear to make use of them. - sprintf(Ptr, "nullptr"); + sprintf(Ptr, "ABCD"); Ptr = Ptr + strlen(Ptr) + 1; - sprintf(Ptr, "nullptr"); + sprintf(Ptr, "ABCD"); Ptr = Ptr + strlen(Ptr) + 1; AvailableTaskTrailer = (AvailableTaskTrailer_Struct*)Ptr; @@ -1253,7 +1253,7 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task // In some packets, this next string looks like a short task summary, however it doesn't // appear anywhere in the client window. - sprintf(Ptr, "nullptr"); + sprintf(Ptr, "ABCD"); Ptr = Ptr + strlen(Ptr) + 1; } From f6100ed83406dcef6ea2c6166acef1654883e9a8 Mon Sep 17 00:00:00 2001 From: mackal Date: Wed, 8 May 2013 17:07:49 -0400 Subject: [PATCH 9/9] Fixed NPC::GetScore and XS_NPC_GetScore --- zone/npc.cpp | 29 ++++++++--------------------- zone/perl_npc.cpp | 2 +- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index cc28aeab4..afba99199 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2432,31 +2432,23 @@ int NPC::GetScore() if(lv < 46) { -#if _MSC_VER==1600 - minx = ceil((float) ((lv - (lv / 10)) - 1) ); -#else - minx = ceil( ((lv - (lv / 10)) - 1) ); -#endif + minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) )); basehp = (lv * 10) + (lv * lv); } else { -#if _MSC_VER==1600 - minx = ceil((float) ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); -#else - minx = ceil( ((lv - (lv / 10)) - 1) - (( abs(45 - lv) ) / 2) ); -#endif + minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) - (( lv - 45.0 ) / 2.0) )); basehp = (lv * 10) + ((lv * lv) * 4); } if(hp > basehp) { - hpcontrib = (int)( (float)((float)hp / (float)basehp) * 1.5); + hpcontrib = static_cast (((hp / static_cast (basehp)) * 1.5)); if(hpcontrib > 5) { hpcontrib = 5; } if(maxdmg > basedmg) { - dmgcontrib = ceil( ((maxdmg / basedmg) * 1.5) ); + dmgcontrib = static_cast (ceil( ((maxdmg / basedmg) * 1.5) )); } if(HasNPCSpecialAtk("E")) { spccontrib++; } //Enrage @@ -2471,17 +2463,12 @@ int NPC::GetScore() } if(npc_spells_id > 12) -#if _MSC_VER==1600 - { - if(lv < 16) { spccontrib++; } - else { spccontrib += (int)floor((float) lv/15); } - } -#else { - if(lv < 16) { spccontrib++; } - else { spccontrib += (int)floor(lv/15); } + if(lv < 16) + spccontrib++; + else + spccontrib += static_cast (floor(lv/15.0)); } -#endif final = minx + hpcontrib + dmgcontrib + spccontrib; final = max(1, final); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index b0eb0ce1a..3888c05ea 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -2236,7 +2236,7 @@ XS(boot_NPC) newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetSlowMitigation, file, "$"); newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); - newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetSpawnKillCount, file, "$"); + newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$"); XSRETURN_YES; }