This commit is contained in:
Arthur Ice
2014-12-05 20:16:13 -08:00
124 changed files with 63220 additions and 2537 deletions
+14 -64
View File
@@ -16,84 +16,34 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Test 1
#include <iostream>
#include "../common/debug.h"
#include "aa.h"
#include "mob.h"
#include "client.h"
#include "groups.h"
#include "raids.h"
#include "../common/spdat.h"
#include "object.h"
#include "doors.h"
#include "beacon.h"
#include "corpse.h"
#include "titles.h"
#include "../common/races.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/eq_packet_structs.h"
#include "../common/packet_dump.h"
#include "../common/races.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/logsys.h"
#include "zonedb.h"
#include "string_ids.h"
#include "aa.h"
#include "client.h"
#include "corpse.h"
#include "groups.h"
#include "mob.h"
#include "queryserv.h"
#include "raids.h"
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
extern QueryServ* QServ;
//static data arrays, really not big enough to warrant shared mem.
AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
std::map<uint32,SendAA_Struct*>aas_send;
std::map<uint32, std::map<uint32, AA_Ability> > aa_effects; //stores the effects from the aa_effects table in memory
std::map<uint32, AALevelCost_Struct> AARequiredLevelAndCost;
/*
Schema:
spell_id is spell to cast, SPELL_UNKNOWN == no spell
nonspell_action is action to preform on activation which is not a spell, 0=none
nonspell_mana is mana that the nonspell action consumes
nonspell_duration is a duration which may be used by the nonspell action
redux_aa is the aa which reduces the reuse timer of the skill
redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster)
CREATE TABLE aa_actions (
aaid mediumint unsigned not null,
rank tinyint unsigned not null,
reuse_time mediumint unsigned not null,
spell_id mediumint unsigned not null,
target tinyint unsigned not null,
nonspell_action tinyint unsigned not null,
nonspell_mana mediumint unsigned not null,
nonspell_duration mediumint unsigned not null,
redux_aa mediumint unsigned not null,
redux_rate tinyint not null,
PRIMARY KEY(aaid, rank)
);
CREATE TABLE aa_swarmpets (
spell_id mediumint unsigned not null,
count tinyint unsigned not null,
npc_id int not null,
duration mediumint unsigned not null,
PRIMARY KEY(spell_id)
);
*/
/*
Credits for this function:
-FatherNitwit: Structure and mechanism
-Wiz: Initial set of AAs, original function contents
-Branks: Much updated info and a bunch of higher-numbered AAs
*/
int Client::GetAATimerID(aaID activate)
{
SendAA_Struct* aa2 = zone->FindAA(activate);
+2 -1
View File
@@ -2,7 +2,8 @@
#ifndef AA_H
#define AA_H
#include "../common/eq_packet_structs.h"
struct AA_Ability;
struct SendAA_Struct;
#define MANA_BURN 664
+3 -3
View File
@@ -329,7 +329,7 @@ bool Mob::CheckWillAggro(Mob *mob) {
||
(
fv == FACTION_THREATENLY
&& MakeRandomInt(0,99) < THREATENLY_ARRGO_CHANCE - heroicCHA_mod
&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
)
)
)
@@ -1254,7 +1254,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
return true;
//1: The mob has a default 25% chance of being allowed a resistance check against the charm.
if (MakeRandomInt(0, 99) > RuleI(Spells, CharmBreakCheckChance))
if (zone->random.Int(0, 99) > RuleI(Spells, CharmBreakCheckChance))
return true;
if (RuleB(Spells, CharismaCharmDuration))
@@ -1273,7 +1273,7 @@ bool Mob::PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id) {
//3: At maxed ability, Total Domination has a 50% chance of preventing the charm break that otherwise would have occurred.
int16 TotalDominationBonus = caster->aabonuses.CharmBreakChance + caster->spellbonuses.CharmBreakChance + caster->itembonuses.CharmBreakChance;
if (MakeRandomInt(0, 99) < TotalDominationBonus)
if (zone->random.Int(0, 99) < TotalDominationBonus)
return true;
}
+76 -91
View File
@@ -21,28 +21,22 @@
#endif
#include "../common/debug.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <assert.h>
#include "masterentity.h"
#include "npc_ai.h"
#include "../common/packet_dump.h"
#include "../common/eq_packet_structs.h"
#include "../common/eq_constants.h"
#include "../common/eq_packet_structs.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "zone.h"
#include "string_ids.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "water_map.h"
#include "worldserver.h"
#include "queryserv.h"
#include "zone.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
extern QueryServ* QServ;
extern WorldServer worldserver;
@@ -345,7 +339,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c
// Did we hit?
//
float tohit_roll = MakeRandomFloat(0, 100);
float tohit_roll = zone->random.Real(0, 100);
mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll);
@@ -421,7 +415,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
//Live AA - HightenedAwareness
int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind;
if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){
if (BlockBehindChance && zone->random.Roll(BlockBehindChance)) {
bBlockFromRear = true;
if (spellbonuses.BlockBehind || itembonuses.BlockBehind)
@@ -514,7 +508,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
}
if(damage > 0){
roll = MakeRandomFloat(0,100);
roll = zone->random.Real(0,100);
if(roll <= RollTable[0]){
damage = -3;
}
@@ -680,7 +674,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
if (acfail>100) acfail=100;
}
if (acfail<=0 || MakeRandomInt(0, 100)>acfail) {
if (acfail<=0 || zone->random.Int(0, 100)>acfail) {
float acreduction=1;
int acrandom=300;
if (database.GetVariable("ACreduction", tmp, 9))
@@ -699,7 +693,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac
damage -= (int32) (GetAC() * acreduction/100.0f);
}
if (acrandom>0) {
damage -= (myac * MakeRandomInt(0, acrandom) / 10000);
damage -= (myac * zone->random.Int(0, acrandom) / 10000);
}
if (damage<1) damage=1;
mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage);
@@ -727,8 +721,8 @@ int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
float mit_rating, float atk_rating)
{
float d = 10.0;
float mit_roll = MakeRandomFloat(0, mit_rating);
float atk_roll = MakeRandomFloat(0, atk_rating);
float mit_roll = zone->random.Real(0, mit_rating);
float atk_roll = zone->random.Real(0, atk_rating);
if (atk_roll > mit_roll) {
float a_diff = atk_roll - mit_roll;
@@ -777,8 +771,8 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit,
dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0);
dmg_interval -= dmg_interval * spellMeleeMit;
float mit_roll = MakeRandomFloat(0, mit_rating);
float atk_roll = MakeRandomFloat(0, atk_rating);
float mit_roll = zone->random.Real(0, mit_rating);
float atk_roll = zone->random.Real(0, atk_rating);
if (atk_roll > mit_roll) {
float a_diff = atk_roll - mit_roll;
@@ -1278,7 +1272,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
damage = mod_client_damage(damage, skillinuse, Hand, weapon, other);
@@ -1320,7 +1314,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
OffhandRiposteFail *= -1; //Live uses a negative value for this.
if (OffhandRiposteFail &&
(OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) {
(OffhandRiposteFail > 99 || zone->random.Roll(OffhandRiposteFail))) {
damage = 0; // Counts as a miss
slippery_attack = true;
} else
@@ -1336,7 +1330,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA
int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) {
if(bonusStrikeThrough && zone->random.Roll(bonusStrikeThrough)) {
Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses!
Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit
return false;
@@ -1362,11 +1356,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
MeleeLifeTap(damage);
if (damage > 0){
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
if (HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
}
if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0)
TrySkillProc(other, skillinuse, 0, true, Hand);
CommonBreakInvisible();
@@ -1631,14 +1622,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
database.GetVariable("PvPitem", tmp2, 9);
int pvpitem = atoi(tmp2);
if(pvpitem>0 && pvpitem<200000)
new_corpse->SetPKItem(pvpitem);
new_corpse->SetPlayerKillItemID(pvpitem);
}
else if(reward==2)
new_corpse->SetPKItem(-1);
new_corpse->SetPlayerKillItemID(-1);
else if(reward==1)
new_corpse->SetPKItem(1);
new_corpse->SetPlayerKillItemID(1);
else
new_corpse->SetPKItem(0);
new_corpse->SetPlayerKillItemID(0);
if(killerMob->CastToClient()->isgrouped) {
Group* group = entity_list.GetGroupByClient(killerMob->CastToClient());
if(group != 0)
@@ -1647,7 +1638,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
{
if(group->members[i] != nullptr)
{
new_corpse->AllowMobLoot(group->members[i],i);
new_corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@@ -1852,7 +1843,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if(RuleB(Combat, UseIntervalAC))
damage = (max_dmg+eleBane);
else
damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane));
damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane));
//check if we're hitting above our max or below it.
@@ -2301,13 +2292,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
if(killer != 0 && emoteid != 0)
corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid);
if(killer != 0 && killer->IsClient()) {
corpse->AllowMobLoot(killer, 0);
corpse->AllowPlayerLoot(killer, 0);
if(killer->IsGrouped()) {
Group* group = entity_list.GetGroupByClient(killer->CastToClient());
if(group != 0) {
for(int i=0;i<6;i++) { // Doesnt work right, needs work
if(group->members[i] != nullptr) {
corpse->AllowMobLoot(group->members[i],i);
corpse->AllowPlayerLoot(group->members[i],i);
}
}
}
@@ -2323,30 +2314,30 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
case 0:
case 1:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 2:
if(r->members[x].member && r->members[x].IsRaidLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
else if(r->members[x].member && r->members[x].IsGroupLeader){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 3:
if(r->members[x].member && r->members[x].IsLooter){
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
case 4:
if(r->members[x].member)
{
corpse->AllowMobLoot(r->members[x].member, i);
corpse->AllowPlayerLoot(r->members[x].member, i);
i++;
}
break;
@@ -2478,9 +2469,8 @@ void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp,
}
}
auto otherPosition = xyz_location(other->GetX(), other->GetY(), other->GetZ());
if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
if(!zone->watermap->InLiquid(otherPosition)) {
if(!zone->watermap->InLiquid(other->GetPosition())) {
return;
}
}
@@ -3448,17 +3438,16 @@ bool Client::CheckDoubleAttack(bool tripleAttack) {
chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers.
}
if((MakeRandomFloat(0, 1) < chance))
if(zone->random.Roll(chance))
return true;
return false;
}
bool Client::CheckDoubleRangedAttack() {
int32 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack;
if(chance && (MakeRandomInt(0, 100) < chance))
if(chance && zone->random.Roll(chance))
return true;
return false;
@@ -3642,7 +3631,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
}
}
if (stun_chance && MakeRandomInt(0, 99) < stun_chance) {
if (stun_chance && zone->random.Roll(stun_chance)) {
// Passed stun, try to resist now
int stun_resist = itembonuses.StunResist + spellbonuses.StunResist;
int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist;
@@ -3655,18 +3644,18 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
// frontal stun check for ogres/bonuses
if (((GetBaseRace() == OGRE && IsClient()) ||
(frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) &&
(frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) &&
!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist);
} else {
// Normal stun resist check.
if (stun_resist && MakeRandomInt(0, 99) < stun_resist) {
if (stun_resist && zone->random.Roll(stun_resist)) {
if (IsClient())
Message_StringID(MT_Stun, SHAKE_OFF_STUN);
mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist);
} else {
mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist);
Stun(MakeRandomInt(0, 2) * 1000); // 0-2 seconds
Stun(zone->random.Int(0, 2) * 1000); // 0-2 seconds
}
}
} else {
@@ -3947,7 +3936,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) {
for (int i = 0; i < MAX_PROCS; i++) {
if (IsValidSpell(DefensiveProcs[i].spellID)) {
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance)/100.0f);
if ((MakeRandomFloat(0, 1) <= chance)) {
if (zone->random.Roll(chance)) {
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
}
@@ -4009,7 +3998,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
if (weapon->Proc.Type == ET_CombatProc) {
float WPC = ProcChance * (100.0f + // Proc chance for this weapon
static_cast<float>(weapon->ProcRate)) / 100.0f;
if (MakeRandomFloat(0, 1) <= WPC) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
if (weapon->Proc.Level > ourlevel) {
mlog(COMBAT__PROCS,
"Tried to proc (%s), but our level (%d) is lower than required (%d)",
@@ -4047,7 +4036,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
if (aug->Proc.Type == ET_CombatProc) {
float APC = ProcChance * (100.0f + // Proc chance for this aug
static_cast<float>(aug->ProcRate)) / 100.0f;
if (MakeRandomFloat(0, 1) <= APC) {
if (zone->random.Roll(APC)) {
if (aug->Proc.Level > ourlevel) {
if (IsPet()) {
Mob *own = GetOwner();
@@ -4100,7 +4089,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
if (!rangedattk) {
// Perma procs (AAs)
if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus?
if (zone->random.Roll(PermaProcs[i].chance)) { // TODO: Do these get spell bonus?
mlog(COMBAT__PROCS,
"Permanent proc %d procing spell %d (%d percent chance)",
i, PermaProcs[i].spellID, PermaProcs[i].chance);
@@ -4115,7 +4104,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
// Spell procs (buffs)
if (SpellProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(SpellProcs[i].chance) / 100.0f);
if (MakeRandomFloat(0, 1) <= chance) {
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
"Spell proc %d procing spell %d (%.2f percent chance)",
i, SpellProcs[i].spellID, chance);
@@ -4131,7 +4120,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
// ranged spell procs (buffs)
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
float chance = ProcChance * (static_cast<float>(RangedProcs[i].chance) / 100.0f);
if (MakeRandomFloat(0, 1) <= chance) {
if (zone->random.Roll(chance)) {
mlog(COMBAT__PROCS,
"Ranged proc %d procing spell %d (%.2f percent chance)",
i, RangedProcs[i].spellID, chance);
@@ -4199,7 +4188,7 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage)
critChance /= 100;
if(MakeRandomFloat(0, 1) < critChance)
if(zone->random.Roll(critChance))
{
critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100
damage = (damage * critMod) / 100;
@@ -4238,7 +4227,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
if (SlayRateBonus) {
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
if (MakeRandomFloat(0, 1) < slayChance) {
if (zone->random.Roll(slayChance)) {
int32 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1];
damage = (damage * SlayDmgBonus * 2.25) / 100;
if (GetGender() == 1) // female
@@ -4309,7 +4298,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
critChance /= 100;
if(MakeRandomFloat(0, 1) < critChance)
if(zone->random.Roll(critChance))
{
uint32 critMod = 200;
bool crip_success = false;
@@ -4322,7 +4311,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
if (!IsBerserk() && !IsBerskerSPA)
critChance *= float(CripplingBlowChance)/100.0f;
if ((IsBerserk() || IsBerskerSPA) || MakeRandomFloat(0, 1) < critChance) {
if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) {
critMod = 400;
crip_success = true;
}
@@ -4332,7 +4321,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack
damage = damage * critMod / 100;
bool deadlySuccess = false;
if (deadlyChance && MakeRandomFloat(0, 1) < static_cast<float>(deadlyChance) / 100.0f) {
if (deadlyChance && zone->random.Roll(static_cast<float>(deadlyChance) / 100.0f)) {
if (BehindMob(defender, GetX(), GetY())) {
damage *= deadlyMod;
deadlySuccess = true;
@@ -4379,7 +4368,7 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
//Proc Chance value of 500 = 5%
uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10;
if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= MakeRandomInt(0, 1000))){
if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= zone->random.Int(0, 1000))){
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false);
return true;
@@ -4406,7 +4395,7 @@ void Mob::DoRiposte(Mob* defender) {
defender->itembonuses.DoubleRiposte;
//Live AA - Double Riposte
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
@@ -4417,7 +4406,7 @@ void Mob::DoRiposte(Mob* defender) {
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance);
if (defender->GetClass() == MONK)
@@ -4529,7 +4518,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (spellbonuses.LimitToSkill[skill]){
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) {
@@ -4548,7 +4536,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, base_spell_id);
CanProc = false;
@@ -4568,7 +4556,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (itembonuses.LimitToSkill[skill]){
CanProc = true;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) {
@@ -4587,7 +4574,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
@@ -4612,7 +4599,6 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
uint32 slot = 0;
for(int e = 0; e < MAX_SKILL_PROCS; e++){
if (CanProc &&
(!Success && aabonuses.SkillProc[e])
|| (Success && aabonuses.SkillProcSuccess[e])){
@@ -4640,7 +4626,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (MakeRandomFloat(0, 1) <= final_chance) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
@@ -4680,26 +4666,25 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
The Viscid Roots AA does the following: Reduces the chance for root to break by X percent.
There is no distinction of any kind between the caster inflicted damage, or anyone
else's damage. There is also no distinction between Direct and DOT damage in the root code.
/*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443
The Viscid Roots AA does the following: Reduces the chance for root to break by X percent.
There is no distinction of any kind between the caster inflicted damage, or anyone
else's damage. There is also no distinction between Direct and DOT damage in the root code.
/* General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- Only roots on determental spells can be broken by damage.
General Mechanics
- Check buffslot to make sure damage from a root does not cancel the root
- If multiple roots on target, always and only checks first root slot and if broken only removes that slots root.
- Only roots on determental spells can be broken by damage.
- Root break chance values obtained from live parses.
*/
*/
if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0)
return false;
return false;
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){
int BreakChance = RuleI(Spells, RootBreakFromSpells);
int BreakChance = RuleI(Spells, RootBreakFromSpells);
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100;
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100;
int level_diff = attacker->GetLevel() - GetLevel();
//Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level)
@@ -4713,10 +4698,10 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
else if (level_diff > 21)
BreakChance = (BreakChance * 20) /100; //Decrease by 80%;
if (BreakChance < 1)
BreakChance = 1;
if (BreakChance < 1)
BreakChance = 1;
if (MakeRandomInt(0, 99) < BreakChance) {
if (zone->random.Roll(BreakChance)) {
if (!TryFadeEffect(spellbonuses.Root[1])) {
BuffFadeBySlot(spellbonuses.Root[1]);
+5054
View File
File diff suppressed because it is too large Load Diff
+74 -74
View File
@@ -775,49 +775,49 @@ void Bot::GenerateAppearance() {
// Randomize facial appearance
int iFace = 0;
if(this->GetRace() == 2) { // Barbarian w/Tatoo
iFace = MakeRandomInt(0, 79);
iFace = zone->random.Int(0, 79);
}
else {
iFace = MakeRandomInt(0, 7);
iFace = zone->random.Int(0, 7);
}
int iHair = 0;
int iBeard = 0;
int iBeardColor = 1;
if(this->GetRace() == 522) {
iHair = MakeRandomInt(0, 8);
iBeard = MakeRandomInt(0, 11);
iBeardColor = MakeRandomInt(0, 3);
iHair = zone->random.Int(0, 8);
iBeard = zone->random.Int(0, 11);
iBeardColor = zone->random.Int(0, 3);
}
else if(this->GetGender()) {
iHair = MakeRandomInt(0, 2);
iHair = zone->random.Int(0, 2);
if(this->GetRace() == 8) { // Dwarven Females can have a beard
if(MakeRandomInt(1, 100) < 50) {
if(zone->random.Int(1, 100) < 50) {
iFace += 10;
}
}
}
else {
iHair = MakeRandomInt(0, 3);
iBeard = MakeRandomInt(0, 5);
iBeardColor = MakeRandomInt(0, 19);
iHair = zone->random.Int(0, 3);
iBeard = zone->random.Int(0, 5);
iBeardColor = zone->random.Int(0, 19);
}
int iHairColor = 0;
if(this->GetRace() == 522) {
iHairColor = MakeRandomInt(0, 3);
iHairColor = zone->random.Int(0, 3);
}
else {
iHairColor = MakeRandomInt(0, 19);
iHairColor = zone->random.Int(0, 19);
}
uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9);
uint8 iEyeColor1 = (uint8)zone->random.Int(0, 9);
uint8 iEyeColor2 = 0;
if(this->GetRace() == 522) {
iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11);
iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11);
}
else if(MakeRandomInt(1, 100) > 96) {
iEyeColor2 = MakeRandomInt(0, 9);
else if(zone->random.Int(1, 100) > 96) {
iEyeColor2 = zone->random.Int(0, 9);
}
else {
iEyeColor2 = iEyeColor1;
@@ -827,9 +827,9 @@ void Bot::GenerateAppearance() {
int iTattoo = 0;
int iDetails = 0;
if(this->GetRace() == 522) {
iHeritage = MakeRandomInt(0, 6);
iTattoo = MakeRandomInt(0, 7);
iDetails = MakeRandomInt(0, 7);
iHeritage = zone->random.Int(0, 6);
iTattoo = zone->random.Int(0, 7);
iDetails = zone->random.Int(0, 7);
}
this->luclinface = iFace;
@@ -3098,7 +3098,7 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) {
chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers.
}
if((MakeRandomFloat(0, 1) < chance))
if((zone->random.Real(0, 1) < chance))
return true;
return false;
@@ -3148,7 +3148,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
if(!other->CheckHitChance(this, skillinuse, Hand, chance_mod)) {
damage = 0;
@@ -3203,7 +3203,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
if (damage > 0)
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && MakeRandomInt(0, 99) < 25){
if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
other->Stun(100);
}
@@ -3483,7 +3483,7 @@ void Bot::AI_Process() {
meleeDistance = meleeDistance * .30;
}
else {
meleeDistance *= (float)MakeRandomFloat(.50, .85);
meleeDistance *= (float)zone->random.Real(.50, .85);
}
bool atArcheryRange = IsArcheryRange(GetTarget());
@@ -3616,7 +3616,7 @@ void Bot::AI_Process() {
if (GetTarget() && flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Int(0, 100) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@@ -3633,7 +3633,7 @@ void Bot::AI_Process() {
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Int(0, 100) < ExtraAttackChanceBonus)
{
Attack(GetTarget(), MainPrimary, false);
}
@@ -3678,7 +3678,7 @@ void Bot::AI_Process() {
int32 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
float random = zone->random.Real(0, 1);
if (random < DualWieldProbability){ // Max 78% of DW
@@ -3912,7 +3912,7 @@ void Bot::PetAIProcess() {
if (botPet->GetTarget()) // Do we still have a target?
{
// We're a pet so we re able to dual attack
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier)))
{
if(botPet->Attack(botPet->GetTarget(), MainPrimary))
@@ -3945,7 +3945,7 @@ void Bot::PetAIProcess() {
//aa_chance += botPet->GetOwner()->GetAA(aaCompanionsAlacrity) * 3;
if (MakeRandomInt(1, 100) < aa_chance)
if (zone->random.Int(1, 100) < aa_chance)
Flurry(nullptr);
}
@@ -3955,12 +3955,12 @@ void Bot::PetAIProcess() {
if(botPet->GetOwner()->GetLevel() >= 24)
{
float DualWieldProbability = (botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f;
DualWieldProbability -= MakeRandomFloat(0, 1);
DualWieldProbability -= zone->random.Real(0, 1);
if(DualWieldProbability < 0){
botPet->Attack(botPet->GetTarget(), MainSecondary);
if (botPet->CanThisClassDoubleAttack())
{
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if (RandRoll < (botPet->GetLevel() + 20))
{
botPet->Attack(botPet->GetTarget(), MainSecondary);
@@ -6213,7 +6213,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if(RuleB(Combat, UseIntervalAC))
damage = max_hit;
else
damage = MakeRandomInt(min_hit, max_hit);
damage = zone->random.Int(min_hit, max_hit);
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, GetLevel());
@@ -6258,7 +6258,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
OffhandRiposteFail *= -1; //Live uses a negative value for this.
if (OffhandRiposteFail &&
(OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) {
(OffhandRiposteFail > 99 || (zone->random.Int(0, 100) < OffhandRiposteFail))) {
damage = 0; // Counts as a miss
slippery_attack = true;
} else
@@ -6274,7 +6274,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
if (((damage < 0) || slippery_attack) && !FromRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA
int32 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) {
if(bonusStrikeThrough && (zone->random.Int(0, 100) < bonusStrikeThrough)) {
Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses!
Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit
return false;
@@ -6623,7 +6623,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
{
if(type == focusTriggerOnCast)
{
if(MakeRandomInt(0, 100) <= base1){
if(zone->random.Int(0, 100) <= base1){
value = base2;
}
@@ -6646,7 +6646,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
{
if(type == focusBlockNextSpell)
{
if(MakeRandomInt(1, 100) <= base1)
if(zone->random.Int(1, 100) <= base1)
value = 1;
}
break;
@@ -6670,7 +6670,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
else
@@ -7147,7 +7147,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -7165,7 +7165,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -7183,7 +7183,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -7273,7 +7273,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
{
if(bottype == BotfocusTriggerOnCast)
if(MakeRandomInt(0, 100) <= focus_spell.base[i])
if(zone->random.Int(0, 100) <= focus_spell.base[i])
value = focus_spell.base2[i];
else
@@ -7293,7 +7293,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
{
if(bottype == BotfocusBlockNextSpell)
{
if(MakeRandomInt(1, 100) <= focus_spell.base[i])
if(zone->random.Int(1, 100) <= focus_spell.base[i])
value = 1;
}
break;
@@ -7313,7 +7313,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
else
@@ -7503,7 +7503,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
//Live AA - HightenedAwareness
int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind;
if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){
if (BlockBehindChance && (BlockBehindChance > zone->random.Int(1, 100))){
bBlockFromRear = true;
if (spellbonuses.BlockBehind || itembonuses.BlockBehind)
@@ -7595,7 +7595,7 @@ bool Bot::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte)
if(damage > 0)
{
roll = MakeRandomFloat(0,100);
roll = zone->random.Real(0,100);
if(roll <= RollTable[0]){
damage = -3;
}
@@ -7662,7 +7662,7 @@ bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
uint32 damage = aabonuses.FinishingBlow[1];
uint16 levelreq = aabonuses.FinishingBlowLvl[0];
if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){
if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))){
mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel());
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName());
defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
@@ -7690,7 +7690,7 @@ void Bot::DoRiposte(Mob* defender) {
defender->GetSpellBonuses().GiveDoubleRiposte[0] +
defender->GetItemBonuses().GiveDoubleRiposte[0];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) {
mlog(COMBAT__ATTACKS, "Preforming a double riposte (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
@@ -7700,7 +7700,7 @@ void Bot::DoRiposte(Mob* defender) {
//Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill]
DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1];
if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) {
if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) {
if (defender->GetClass() == MONK)
defender->MonkSpecialAttack(this, defender->GetAABonuses().GiveDoubleRiposte[2]);
else if (defender->IsBot())
@@ -7766,7 +7766,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
int kb_chance = 25;
kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100;
if (MakeRandomInt(0, 99) < kb_chance)
if (zone->random.Int(0, 99) < kb_chance)
SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff);
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
}
@@ -7807,7 +7807,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
//Live AA - Seized Opportunity
int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance;
if (FrontalBSChance && (FrontalBSChance > MakeRandomInt(0, 100)))
if (FrontalBSChance && (FrontalBSChance > zone->random.Int(0, 100)))
bCanFrontalBS = true;
}
@@ -7821,7 +7821,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
!other->CastToNPC()->IsEngaged() && // not aggro
other->GetHP()<=32000
&& other->IsNPC()
&& MakeRandomFloat(0, 99) < chance // chance
&& zone->random.Real(0, 99) < chance // chance
) {
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName());
RogueAssassinate(other);
@@ -7832,12 +7832,12 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
// Check for double attack with main hand assuming maxed DA Skill (MS)
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
{
if(other->GetHP() > 0)
RogueBackstab(other,false,ReuseTime);
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100))
RogueBackstab(other,false,ReuseTime);
}
}
@@ -7851,11 +7851,11 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
if (level > 54) {
float DoubleAttackProbability = (GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f; // 62.4 max
// Check for double attack with main hand assuming maxed DA Skill (MS)
if(MakeRandomFloat(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(zone->random.Real(0, 1) < DoubleAttackProbability) // Max 62.4 % chance of DA
if(other->GetHP() > 0)
RogueBackstab(other,true, ReuseTime);
if (tripleChance && other->GetHP() > 0 && tripleChance > MakeRandomInt(0, 100))
if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100))
RogueBackstab(other,false,ReuseTime);
}
}
@@ -7929,7 +7929,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
if(RuleB(Combat, UseIntervalAC))
ndamage = max_hit;
else
ndamage = MakeRandomInt(min_hit, max_hit);
ndamage = zone->random.Int(min_hit, max_hit);
}
}
@@ -8036,7 +8036,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
canBash = true;
}
if(!canBash || MakeRandomInt(0, 100) > 25) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
if(!canBash || zone->random.Int(0, 100) > 25) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
skill_to_use = SkillKick;
}
else {
@@ -8117,7 +8117,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetBashDamage();
else
dmg = MakeRandomInt(1, GetBashDamage());
dmg = zone->random.Int(1, GetBashDamage());
}
}
@@ -8164,7 +8164,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
//Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit.
while(AtkRounds > 0) {
if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){
if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0,100) < 75)){
DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , reuse, true);
}
AtkRounds--;
@@ -8192,7 +8192,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetKickDamage();
else
dmg = MakeRandomInt(1, GetKickDamage());
dmg = zone->random.Int(1, GetKickDamage());
}
}
@@ -8215,18 +8215,18 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
//Live AA - Technique of Master Wu
uint32 bDoubleSpecialAttack = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack;
if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > MakeRandomInt(0,100))) {
if( bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0,100))) {
int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick };
MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]);
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]);
int TripleChance = 25;
if (bDoubleSpecialAttack > 100)
TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100;
if(TripleChance > MakeRandomInt(0,100)) {
MonkSpecialAttack(target, MonkSPA[MakeRandomInt(0,4)]);
if(TripleChance > zone->random.Int(0,100)) {
MonkSpecialAttack(target, MonkSPA[zone->random.Int(0,4)]);
}
}
@@ -8259,7 +8259,7 @@ bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
// WildcardX: These chance formula's below are arbitrary. If someone has a better formula that is more
// consistent with live, feel free to update these.
float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f);
float DefenderChance = (float)MakeRandomFloat(0.00f, 1.00f);
float DefenderChance = (float)zone->random.Real(0.00f, 1.00f);
if(AttackerChance > DefenderChance) {
mlog(COMBAT__ATTACKS, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance);
// WildcardX: At the time I wrote this, there wasnt a string id for something like HEADSHOT_BLOW
@@ -8734,14 +8734,14 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100;
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Int(1,100) <= chance){
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Int(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
Critical = true;
}
@@ -8820,7 +8820,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && (zone->random.Int(0,99) < chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@@ -8851,7 +8851,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && (zone->random.Int(0,99) < chance))
return (value * 2);
}
@@ -8950,7 +8950,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int32 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int32 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@@ -8963,7 +8963,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = MakeRandomInt(0, 100);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
@@ -9015,7 +9015,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
@@ -11864,7 +11864,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
}
if(!strcasecmp(sep->arg[1], "inventory") && !strcasecmp(sep->arg[2], "remove")) {
if((c->GetTarget() == nullptr) || (sep->arg[3] == '\0') || !c->GetTarget()->IsBot())
if((c->GetTarget() == nullptr) || (sep->arg[3][0] == '\0') || !c->GetTarget()->IsBot())
{
c->Message(15, "Usage: #bot inventory remove [slotid] (You must have a bot targetted) ");
return;
@@ -15580,7 +15580,7 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl
return false;
if (iChance < 100) {
uint8 tmp = MakeRandomInt(1, 100);
uint8 tmp = zone->random.Int(1, 100);
if (tmp > iChance)
return false;
}
+4 -4
View File
@@ -13,7 +13,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) > iChance){
if (zone->random.Int(0, 100) > iChance){
return false;
}
}
@@ -485,7 +485,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
if(botClass == PALADIN)
stunChance = 50;
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (MakeRandomInt(1, 100) <= stunChance)) {
if(!tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned() && (zone->random.Int(1, 100) <= stunChance)) {
botSpell = GetBestBotSpellForStunByTargetType(this, ST_Target);
}
}
@@ -1843,7 +1843,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
result = std::string("SumEarth");
else if(botCaster->GetLevel() < 30) {
// Under level 30
int counter = MakeRandomInt(0, 3);
int counter = zone->random.Int(0, 3);
switch(counter) {
case 0:
@@ -1865,7 +1865,7 @@ std::string Bot::GetBotMagicianPetType(Bot* botCaster) {
}
else {
// Over level 30
int counter = MakeRandomInt(0, 4);
int counter = zone->random.Int(0, 4);
switch(counter) {
case 0:
+28 -26
View File
@@ -17,13 +17,9 @@
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <math.h>
// for windows compile
#ifdef _WINDOWS
@@ -39,27 +35,17 @@
extern volatile bool RunLoops;
#include "../common/features.h"
#include "../common/misc.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/breakdowns.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/data_verification.h"
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "zonedb.h"
#include "petitions.h"
#include "forage.h"
#include "command.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "client_logs.h"
#include "guild_mgr.h"
#include "quest_parser_collection.h"
@@ -1879,6 +1865,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialPrimary] = atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialPrimary] = inst->GetOrnamentationIDFile();
}
else {
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
@@ -1891,6 +1880,9 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
if (strlen(item->IDFile) > 2)
ns->spawn.equipment[MaterialSecondary] = atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
ns->spawn.equipment[MaterialSecondary] = inst->GetOrnamentationIDFile();
}
else {
item = inst->GetItem();
if (strlen(item->IDFile) > 2)
@@ -2326,7 +2318,7 @@ bool Client::CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int cha
if(Chance < 1)
Chance = 1; // Make it always possible
if(MakeRandomFloat(0, 99) < Chance)
if(zone->random.Real(0, 99) < Chance)
{
SetSkill(skillid, GetRawSkill(skillid) + 1);
_log(SKILLS__GAIN, "Skill %d at value %d successfully gain with %.4f%%chance (mod %d)", skillid, skillval, Chance, chancemodi);
@@ -2354,7 +2346,7 @@ void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) {
int32 Chance = 5 + ((TeacherSkill - LangSkill)/10); // greater chance to learn if teacher's skill is much higher than yours
Chance = (Chance * RuleI(Character, SkillUpModifier)/100);
if(MakeRandomFloat(0,100) < Chance) { // if they make the roll
if(zone->random.Real(0,100) < Chance) { // if they make the roll
IncreaseLanguageSkill(langid); // increase the language skill by 1
_log(SKILLS__GAIN, "Language %d at value %d successfully gain with %.4f%%chance", langid, LangSkill, Chance);
}
@@ -2756,6 +2748,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2);
}
else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
m_pp.item_material[MaterialPrimary] = inst->GetOrnamentationIDFile();
}
else {
m_pp.item_material[MaterialPrimary] = atoi(item->IDFile + 2);
}
@@ -2766,6 +2761,9 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2);
}
else if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
m_pp.item_material[MaterialSecondary] = inst->GetOrnamentationIDFile();
}
else {
m_pp.item_material[MaterialSecondary] = atoi(item->IDFile + 2);
}
@@ -4896,7 +4894,7 @@ int Client::LDoNChest_SkillCheck(NPC *target, int skill)
chance = 100.0f - base_difficulty;
}
float d100 = (float)MakeRandomFloat(0, 100);
float d100 = (float)zone->random.Real(0, 100);
if(d100 <= chance)
return 1;
@@ -5815,6 +5813,10 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = aug_weap->Icon;
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = inst->GetOrnamentationIcon();
}
else {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = item->Icon;
@@ -7591,9 +7593,9 @@ void Client::GarbleMessage(char *message, uint8 variance)
const char alpha_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // only change alpha characters for now
for (size_t i = 0; i < strlen(message); i++) {
uint8 chance = (uint8)MakeRandomInt(0, 115); // variation just over worst possible scrambling
uint8 chance = (uint8)zone->random.Int(0, 115); // variation just over worst possible scrambling
if (isalpha(message[i]) && (chance <= variance)) {
uint8 rand_char = (uint8)MakeRandomInt(0,51); // choose a random character from the alpha list
uint8 rand_char = (uint8)zone->random.Int(0,51); // choose a random character from the alpha list
message[i] = alpha_list[rand_char];
}
}
@@ -7711,7 +7713,7 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
// If our result is truncated, then double a mob's value every once and a while to equal what they would have got
else
{
if (MakeRandomInt(0, 100) < faction_mod)
if (zone->random.Int(0, 100) < faction_mod)
npc_value[i] *= 2;
}
}
@@ -7804,11 +7806,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
}
// If no primary faction or biggest influence is your faction hit
if (primaryfaction <= 0 || lowestvalue == tmpFactionValue) {
merchant->Say_StringID(MakeRandomInt(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6));
merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6));
} else if (lowestvalue == fmod.race_mod) { // race biggest
// Non-standard race (ex. illusioned to wolf)
if (GetRace() > PLAYER_RACE_COUNT) {
messageid = MakeRandomInt(1, 3); // these aren't sequential StringIDs :(
messageid = zone->random.Int(1, 3); // these aren't sequential StringIDs :(
switch (messageid) {
case 1:
messageid = WONT_SELL_NONSTDRACE1;
@@ -7825,7 +7827,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
}
merchant->Say_StringID(messageid);
} else { // normal player races
messageid = MakeRandomInt(1, 4);
messageid = zone->random.Int(1, 4);
switch (messageid) {
case 1:
messageid = WONT_SELL_RACE1;
@@ -7846,7 +7848,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
merchant->Say_StringID(messageid, itoa(GetRace()));
}
} else if (lowestvalue == fmod.class_mod) {
merchant->Say_StringID(MakeRandomInt(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass()));
merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass()));
}
return;
}
@@ -7949,7 +7951,7 @@ void Client::TryItemTick(int slot)
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 <= EmuConstants::EQUIPMENT_END) )
if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EmuConstants::EQUIPMENT_END) )
{
ItemInst* e_inst = (ItemInst*)inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);
@@ -7968,7 +7970,7 @@ void Client::TryItemTick(int slot)
if(zone->tick_items.count(iid) > 0)
{
if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) )
if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) )
{
ItemInst* e_inst = (ItemInst*)a_inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);
+8389
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -810,7 +810,7 @@ public:
void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false);
void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0);
bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0);
void SetStats(uint8 type,int16 set_val);
void IncStats(uint8 type,int16 increase_val);
void DropItem(int16 slot_id);
+5 -11
View File
@@ -18,23 +18,17 @@
#include <algorithm>
#include "../common/debug.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/spdat.h"
#include "../common/rulesys.h"
#include "masterentity.h"
#include "worldserver.h"
#include "zonedb.h"
#include "npc_ai.h"
#include "petitions.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "worldserver.h"
#include "zonedb.h"
// Return max stat value for level
int32 Client::GetMaxStat() const {
if((RuleI(Character, StatCap)) > 0)
+63 -82
View File
@@ -16,14 +16,11 @@
*/
#include "../common/debug.h"
#include <assert.h>
#include <iomanip>
#include <iostream>
#include <math.h>
#include <set>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
@@ -38,39 +35,28 @@
#include <unistd.h>
#endif
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "worldserver.h"
#include "../common/rdtsc.h"
#include "../common/packet_dump_file.h"
#include "../common/string_util.h"
#include "../common/breakdowns.h"
#include "../common/guilds.h"
#include "../common/rulesys.h"
#include "../common/spdat.h"
#include "../common/data_verification.h"
#include "petitions.h"
#include "npc_ai.h"
#include "../common/skills.h"
#include "forage.h"
#include "zone.h"
#include "event_codes.h"
#include "../common/faction.h"
#include "../common/crc32.h"
#include "../common/data_verification.h"
#include "../common/faction.h"
#include "../common/guilds.h"
#include "../common/rdtsc.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/zone_numbers.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include "merc.h"
#include "petitions.h"
#include "pets.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "worldserver.h"
#include "zone.h"
#include "zone_config.h"
#include "guild_mgr.h"
#include "pathing.h"
#include "water_map.h"
#include "merc.h"
#include "pets.h"
#include "../common/zone_numbers.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
extern QueryServ* QServ;
extern Zone* zone;
@@ -474,10 +460,10 @@ int Client::HandlePacket(const EQApplicationPacket *app)
mlog(CLIENT__NET_ERR, "Unhandled incoming opcode: %s", buffer);
if(app->size < 1000)
DumpPacket(app->pBuffer, app->size);
DumpPacket(app, app->size);
else{
std::cout << "Dump limited to 1000 characters:\n";
DumpPacket(app->pBuffer, 1000);
DumpPacket(app, 1000);
}
#endif
break;
@@ -2968,7 +2954,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app)
if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == ItemType1HPiercing) ||
(SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == ItemType1HPiercing)) {
float SuccessChance = (GetSkill(SkillApplyPoison) + GetLevel()) / 400.0f;
double ChanceRoll = MakeRandomFloat(0, 1);
double ChanceRoll = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillApplyPoison, nullptr, 10);
@@ -3642,14 +3628,14 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app)
return;
}
int RandomChance = MakeRandomInt(0, 100);
int RandomChance = zone->random.Int(0, 100);
int ChanceToAttack = 0;
if (GetLevel() > GetTarget()->GetLevel())
ChanceToAttack = MakeRandomInt(0, 15);
ChanceToAttack = zone->random.Int(0, 15);
else
ChanceToAttack = MakeRandomInt(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10));
ChanceToAttack = zone->random.Int(((this->GetTarget()->GetLevel() - this->GetLevel()) * 10) - 5, ((this->GetTarget()->GetLevel() - this->GetLevel()) * 10));
if (ChanceToAttack < 0)
ChanceToAttack = -ChanceToAttack;
@@ -3668,7 +3654,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app)
if (RandomChance < ChanceToBeg)
{
brs->Amount = MakeRandomInt(1, 10);
brs->Amount = zone->random.Int(1, 10);
// This needs some work to determine how much money they can beg, based on skill level etc.
if (CurrentSkill < 50)
{
@@ -4537,7 +4523,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
m_Delta = xyz_heading(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading);
if(IsTracking() && ((m_Position.m_X!=ppu->x_pos) || (m_Position.m_Y!=ppu->y_pos))){
if(MakeRandomFloat(0, 100) < 70)//should be good
if(zone->random.Real(0, 100) < 70)//should be good
CheckIncreaseSkill(SkillTracking, nullptr, -20);
}
@@ -5235,16 +5221,16 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app)
if (trap && trap->detected)
{
int uskill = GetSkill(SkillDisarmTraps);
if ((MakeRandomInt(0, 49) + uskill) >= (MakeRandomInt(0, 49) + trap->skill))
if ((zone->random.Int(0, 49) + uskill) >= (zone->random.Int(0, 49) + trap->skill))
{
Message(MT_Skills, "You disarm a trap.");
trap->disarmed = true;
trap->chkarea_timer.Disable();
trap->respawn_timer.Start((trap->respawn_time + MakeRandomInt(0, trap->respawn_var)) * 1000);
trap->respawn_timer.Start((trap->respawn_time + zone->random.Int(0, trap->respawn_var)) * 1000);
}
else
{
if (MakeRandomInt(0, 99) < 25){
if (zone->random.Int(0, 99) < 25){
Message(MT_Skills, "You set off the trap while trying to disarm it!");
trap->Trigger(this);
}
@@ -5605,7 +5591,7 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app)
secfeign = 0;
uint16 totalfeign = primfeign + secfeign;
if (MakeRandomFloat(0, 160) > totalfeign) {
if (zone->random.Real(0, 160) > totalfeign) {
SetFeigned(false);
entity_list.MessageClose_StringID(this, false, 200, 10, STRING_FEIGNFAILED, GetName());
}
@@ -7869,7 +7855,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app)
p_timers.Start(pTimerHide, reuse - 1);
float hidechance = ((GetSkill(SkillHide) / 250.0f) + .25) * 100;
float random = MakeRandomFloat(0, 100);
float random = zone->random.Real(0, 100);
CheckIncreaseSkill(SkillHide, nullptr, 5);
if (random < hidechance) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct));
@@ -7893,7 +7879,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app)
Mob *evadetar = GetTarget();
if (!auto_attack && (evadetar && evadetar->CheckAggro(this)
&& evadetar->IsNPC())) {
if (MakeRandomInt(0, 260) < (int)GetSkill(SkillHide)) {
if (zone->random.Int(0, 260) < (int)GetSkill(SkillHide)) {
msg->string_id = EVADE_SUCCESS;
RogueEvade(evadetar);
}
@@ -8000,6 +7986,10 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app)
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = aug_weap->Icon;
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = inst->GetOrnamentationIcon();
}
else {
strcpy(insr->itemnames[L], item->Name);
insr->itemicons[L] = item->Icon;
@@ -9272,11 +9262,11 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app)
int mendhp = GetMaxHP() / 4;
int currenthp = GetHP();
if (MakeRandomInt(0, 199) < (int)GetSkill(SkillMend)) {
if (zone->random.Int(0, 199) < (int)GetSkill(SkillMend)) {
int criticalchance = spellbonuses.CriticalMend + itembonuses.CriticalMend + aabonuses.CriticalMend;
if (MakeRandomInt(0, 99) < criticalchance){
if (zone->random.Int(0, 99) < criticalchance){
mendhp *= 2;
Message_StringID(4, MEND_CRITICAL);
}
@@ -9291,7 +9281,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app)
0 skill - 25% chance to worsen
20 skill - 23% chance to worsen
50 skill - 16% chance to worsen */
if ((GetSkill(SkillMend) <= 75) && (MakeRandomInt(GetSkill(SkillMend), 100) < 75) && (MakeRandomInt(1, 3) == 1))
if ((GetSkill(SkillMend) <= 75) && (zone->random.Int(GetSkill(SkillMend), 100) < 75) && (zone->random.Int(1, 3) == 1))
{
SetHP(currenthp > mendhp ? (GetHP() - mendhp) : 1);
SendHPUpdate();
@@ -9598,7 +9588,7 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app)
TakeMoneyFromPP(cost, true);
}
// 0 is approved hire request
// approved hire request
SendMercMerchantResponsePacket(0);
}
else
@@ -10596,37 +10586,28 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
case RaidCommandInviteIntoExisting:
case RaidCommandInvite: {
Client *i = entity_list.GetClientByName(ri->player_name);
if (i){
Group *g = i->GetGroup();
if (g){
if (g->IsLeader(i) == false)
Message(13, "You can only invite an ungrouped player or group leader to join your raid.");
else{
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
}
}
else{
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
}
if (!i)
break;
Group *g = i->GetGroup();
// These two messages should be generated by the client I think, just do this for now
if (i->HasRaid()) {
Message(13, "%s is already in a raid.", i->GetName());
break;
}
if (g && !g->IsLeader(i)) {
Message(13, "You can only invite an ungrouped player or group leader to join your raid.");
break;
}
//This sends an "invite" to the client in question.
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer;
strn0cpy(rg->leader_name, ri->leader_name, 64);
strn0cpy(rg->player_name, ri->player_name, 64);
rg->parameter = 0;
rg->action = 20;
i->QueuePacket(outapp);
safe_delete(outapp);
break;
}
case RaidCommandAcceptInvite: {
@@ -11192,7 +11173,7 @@ void Client::Handle_OP_RandomReq(const EQApplicationPacket *app)
randLow = 0;
randHigh = 100;
}
randResult = MakeRandomInt(randLow, randHigh);
randResult = zone->random.Int(randLow, randHigh);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RandomReply, sizeof(RandomReply_Struct));
RandomReply_Struct* rr = (RandomReply_Struct*)outapp->pBuffer;
@@ -11682,7 +11663,7 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app)
if (trap && trap->skill > 0) {
int uskill = GetSkill(SkillSenseTraps);
if ((MakeRandomInt(0, 99) + uskill) >= (MakeRandomInt(0, 99) + trap->skill*0.75))
if ((zone->random.Int(0, 99) + uskill) >= (zone->random.Int(0, 99) + trap->skill*0.75))
{
auto diff = trap->m_Position - GetPosition();
@@ -12425,7 +12406,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app)
// 1199 I don't have time for that now. etc
if (!tmp->CastToNPC()->IsMerchantOpen()) {
tmp->Say_StringID(MakeRandomInt(1199, 1202));
tmp->Say_StringID(zone->random.Int(1199, 1202));
action = 0;
}
@@ -12480,7 +12461,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app)
CheckIncreaseSkill(SkillSneak, nullptr, 5);
}
float hidechance = ((GetSkill(SkillSneak) / 300.0f) + .25) * 100;
float random = MakeRandomFloat(0, 99);
float random = zone->random.Real(0, 99);
if (!was && random < hidechance) {
sneaking = true;
}
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,4 +1,4 @@
// connecting opcode handlers
/* Connecting OpCode Handlers */
void Handle_Connect_0x3e33(const EQApplicationPacket *app);
void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app);
void Handle_Connect_OP_ClientError(const EQApplicationPacket *app);
@@ -20,7 +20,7 @@
void Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app);
void Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app);
// connected opcode handlers
/* Connected opcode handlers*/
void Handle_0x0193(const EQApplicationPacket *app);
void Handle_0x01e7(const EQApplicationPacket *app);
void Handle_OP_AAAction(const EQApplicationPacket *app);
+21 -36
View File
@@ -20,13 +20,8 @@
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <zlib.h>
#include <assert.h>
#ifdef _WINDOWS
#include <windows.h>
@@ -41,29 +36,20 @@
#include <unistd.h>
#endif
#include "masterentity.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "worldserver.h"
#include "../common/packet_dump_file.h"
#include "../common/string_util.h"
#include "../common/spdat.h"
#include "petitions.h"
#include "npc_ai.h"
#include "../common/skills.h"
#include "forage.h"
#include "zone.h"
#include "event_codes.h"
#include "../common/faction.h"
#include "../common/crc32.h"
#include "../common/rulesys.h"
#include "string_ids.h"
#include "map.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include <string>
#include "quest_parser_collection.h"
#include "map.h"
#include "petitions.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
extern QueryServ* QServ;
extern Zone* zone;
@@ -440,7 +426,7 @@ bool Client::Process() {
if (auto_attack_target && flurrychance)
{
if(MakeRandomInt(0, 99) < flurrychance)
if(zone->random.Int(0, 99) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(auto_attack_target, MainPrimary, false);
@@ -457,7 +443,7 @@ bool Client::Process() {
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 99) < ExtraAttackChanceBonus)
if(zone->random.Int(0, 99) < ExtraAttackChanceBonus)
{
Attack(auto_attack_target, MainPrimary, false);
}
@@ -502,7 +488,7 @@ bool Client::Process() {
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
float random = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10);
if (random < DualWieldProbability){ // Max 78% of DW
if(CheckAAEffect(aaEffectRampage)) {
@@ -567,9 +553,8 @@ bool Client::Process() {
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
DoGravityEffect();
@@ -1006,7 +991,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required)
continue;
handychance = MakeRandomInt(0, merlist.size() + tmp_merlist.size() - 1);
handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1);
item = database.GetItem(ml.item);
if (item) {
@@ -1082,7 +1067,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
zone->tmpmerchanttable[npcid] = tmp_merlist;
if (merch != nullptr && handyitem) {
char handy_id[8] = { 0 };
int greeting = MakeRandomInt(0, 4);
int greeting = zone->random.Int(0, 4);
int greet_id = 0;
switch (greeting) {
case 1:
@@ -1643,7 +1628,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
// welcome message
if (pTrainer && pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1204, 1207), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1204, 1207), GetCleanName());
}
}
@@ -1670,7 +1655,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app)
// goodbye message
if (pTrainer->IsNPC())
{
pTrainer->Say_StringID(MakeRandomInt(1208, 1211), GetCleanName());
pTrainer->Say_StringID(zone->random.Int(1208, 1211), GetCleanName());
}
}
@@ -2162,7 +2147,7 @@ void Client::HandleRespawnFromHover(uint32 Option)
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
corpse->IsRezzed(true);
corpse->CompleteRezz();
corpse->CompleteResurrection();
}
}
else //Not rez
File diff suppressed because it is too large Load Diff
+24 -206
View File
@@ -42,38 +42,34 @@
#endif
#include "../common/debug.h"
#include "../common/ptimer.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/serverinfo.h"
#include "../common/opcodemgr.h"
#include "../common/eq_packet.h"
#include "../common/guilds.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
//#include "../common/servertalk.h" // for oocmute and revoke
#include "worldserver.h"
#include "masterentity.h"
#include "map.h"
#include "water_map.h"
#include "../common/features.h"
#include "pathing.h"
#include "client_logs.h"
#include "guild_mgr.h"
#include "titles.h"
#include "../common/guilds.h"
#include "../common/patches/patches.h"
#include "../common/ptimer.h"
#include "../common/rulesys.h"
#include "../common/serverinfo.h"
#include "../common/string_util.h"
#include "client_logs.h"
#include "command.h"
#include "guild_mgr.h"
#include "map.h"
#include "pathing.h"
#include "qglobals.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "worldserver.h"
extern QueryServ* QServ;
extern WorldServer worldserver;
extern TaskManager *taskmanager;
void CatchSignal(int sig_num);
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "command.h"
#include "qglobals.h"
//struct cl_struct *commandlist; // the actual linked list of commands
int commandcount; // how many commands we have
@@ -3416,7 +3412,7 @@ void command_corpse(Client *c, const Seperator *sep)
c->Message(0, "Error: Target must be a player corpse.");
else if (c->Admin() >= commandEditPlayerCorpses && target->IsPlayerCorpse()) {
c->Message(0, "Depoping %s.", target->GetName());
target->CastToCorpse()->DepopCorpse();
target->CastToCorpse()->DepopPlayerCorpse();
if(!sep->arg[2][0] || atoi(sep->arg[2]) != 0)
target->CastToCorpse()->Bury();
}
@@ -3901,7 +3897,7 @@ void command_save(Client *c, const Seperator *sep)
}
else if (c->GetTarget()->IsPlayerCorpse()) {
if (c->GetTarget()->CastToMob()->Save())
c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetDBID());
c->Message(0, "%s successfully saved. (dbid=%u)", c->GetTarget()->GetName(), c->GetTarget()->CastToCorpse()->GetCorpseDBID());
else
c->Message(0, "Manual save for %s failed.", c->GetTarget()->GetName());
}
@@ -4984,189 +4980,10 @@ void command_randomfeatures(Client *c, const Seperator *sep)
c->Message(0,"Error: This command requires a target");
else
{
uint16 Race = target->GetRace();
if (Race <= 12 || Race == 128 || Race == 130 || Race == 330 || Race == 522) {
uint8 Gender = target->GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = 0xFF;
uint8 BeardColor = 0xFF;
uint8 EyeColor1 = 0xFF;
uint8 EyeColor2 = 0xFF;
uint8 HairStyle = 0xFF;
uint8 LuclinFace = 0xFF;
uint8 Beard = 0xFF;
uint32 DrakkinHeritage = 0xFFFFFFFF;
uint32 DrakkinTattoo = 0xFFFFFFFF;
uint32 DrakkinDetails = 0xFFFFFFFF;
// Set some common feature settings
EyeColor1 = MakeRandomInt(0, 9);
EyeColor2 = MakeRandomInt(0, 9);
LuclinFace = MakeRandomInt(0, 7);
// Adjust all settings based on the min and max for each feature of each race and gender
switch (Race)
{
case 1: // Human
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 2: // Barbarian
HairColor = MakeRandomInt(0, 19);
LuclinFace = MakeRandomInt(0, 87);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 3: // Erudite
if (Gender == 0) {
BeardColor = MakeRandomInt(0, 19);
Beard = MakeRandomInt(0, 5);
LuclinFace = MakeRandomInt(0, 57);
}
if (Gender == 1) {
LuclinFace = MakeRandomInt(0, 87);
}
break;
case 4: // WoodElf
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 5: // HighElf
HairColor = MakeRandomInt(0, 14);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 6: // DarkElf
HairColor = MakeRandomInt(13, 18);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 7: // HalfElf
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
LuclinFace = MakeRandomInt(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 8: // Dwarf
HairColor = MakeRandomInt(0, 19);
BeardColor = HairColor;
if (Gender == 0) {
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
LuclinFace = MakeRandomInt(0, 17);
}
break;
case 9: // Troll
EyeColor1 = MakeRandomInt(0, 10);
EyeColor2 = MakeRandomInt(0, 10);
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 3);
HairColor = MakeRandomInt(0, 23);
}
break;
case 10: // Ogre
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 3);
HairColor = MakeRandomInt(0, 23);
}
break;
case 11: // Halfling
HairColor = MakeRandomInt(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 12: // Gnome
HairColor = MakeRandomInt(0, 24);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = MakeRandomInt(0, 3);
Beard = MakeRandomInt(0, 5);
}
if (Gender == 1) {
HairStyle = MakeRandomInt(0, 2);
}
break;
case 128: // Iksar
case 130: // VahShir
break;
case 330: // Froglok
LuclinFace = MakeRandomInt(0, 9);
case 522: // Drakkin
HairColor = MakeRandomInt(0, 3);
BeardColor = HairColor;
EyeColor1 = MakeRandomInt(0, 11);
EyeColor2 = MakeRandomInt(0, 11);
LuclinFace = MakeRandomInt(0, 6);
DrakkinHeritage = MakeRandomInt(0, 6);
DrakkinTattoo = MakeRandomInt(0, 7);
DrakkinDetails = MakeRandomInt(0, 7);
if (Gender == 0) {
Beard = MakeRandomInt(0, 12);
HairStyle = MakeRandomInt(0, 8);
}
if (Gender == 1) {
Beard = MakeRandomInt(0, 3);
HairStyle = MakeRandomInt(0, 7);
}
break;
default:
break;
}
target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
DrakkinHeritage, DrakkinTattoo, DrakkinDetails);
c->Message(0,"NPC Features Randomized");
}
if (target->RandomizeFeatures())
c->Message(0,"Features Randomized");
else
c->Message(0,"This command requires a Playable Race as the Target");
c->Message(0,"This command requires a Playable Race as the target");
}
}
@@ -9999,7 +9816,8 @@ void command_object(Client *c, const Seperator *sep)
// Couldn't copy the object.
if (results.ErrorMessage().c_str() != '\0') {
// got an error message
if (!results.Success()) {
c->Message(0, "Database Error: %s", results.ErrorMessage().c_str());
return;
}
+4 -3
View File
@@ -20,9 +20,10 @@
#ifndef COMMAND_H
#define COMMAND_H
#include "../common/seperator.h"
#include "../common/eq_stream.h"
#include "client.h"
class Client;
class Seperator;
#include "../common/types.h"
#define COMMAND_CHAR '#'
#define CMDALIASES 5
+18
View File
@@ -459,6 +459,24 @@ struct Shielders_Struct {
uint16 shielder_bonus;
};
typedef struct
{
uint16 increment;
uint16 hit_increment;
uint16 target_id;
int32 wpn_dmg;
float origin_x;
float origin_y;
float origin_z;
float tlast_x;
float tlast_y;
uint32 ranged_id;
uint32 ammo_id;
int ammo_slot;
uint8 skill;
float speed_mod;
} tProjatk;
//eventually turn this into a typedef and
//make DoAnim take it instead of int, to enforce its use.
enum { //type arguments to DoAnim
+125 -202
View File
@@ -63,7 +63,7 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) {
safe_delete(outapp);
}
Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard)
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard)
{
uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid);
char *buffer = new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))];
@@ -76,7 +76,6 @@ Corpse* Corpse::LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_
for (unsigned int i = 0; i < pcs->itemcount; i++) {
tmp = new ServerLootItem_Struct;
memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct));
tmp->equip_slot = CorpseToServerSlot(tmp->equip_slot);
itemlist.push_back(tmp);
}
@@ -147,13 +146,15 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0),
corpse_decay_timer(in_decaytime),
corpse_res_timer(0),
corpse_rez_timer(0),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(0),
loot_cooldown_timer(10)
{
corpse_graveyard_timer.Disable();
memset(item_tint, 0, sizeof(item_tint));
is_corpse_changed = false;
is_player_corpse = false;
is_locked = false;
@@ -166,11 +167,11 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
SetCash(in_npc->GetCopper(), in_npc->GetSilver(), in_npc->GetGold(), in_npc->GetPlatinum());
npctype_id = in_npctypeid;
SetPKItem(0);
SetPlayerKillItemID(0);
char_id = 0;
corpse_db_id = 0;
player_corpse_depop = false;
strcpy(orgname, in_npc->GetName());
strcpy(corpse_name, in_npc->GetName());
strcpy(name, in_npc->GetName());
// Added By Hogie
for(int count = 0; count < 100; count++) {
@@ -183,6 +184,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
corpse_decay_timer.SetTimer(RuleI(NPC,EmptyNPCCorpseDecayTimeMS)+1000);
}
if(in_npc->HasPrivateCorpse()) {
corpse_delay_timer.SetTimer(corpse_decay_timer.GetRemainingTime() + 1000);
}
@@ -191,7 +193,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP
for (int i = 0; i < MAX_LOOTERS; i++){
allowed_looters[i] = 0;
}
this->rezzexp = 0;
this->rez_experience = 0;
}
Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
@@ -244,7 +246,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
0 // uint32 in_scalerate
),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_res_timer(RuleI(Character, CorpseResTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
loot_cooldown_timer(10)
@@ -266,8 +268,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
}
is_corpse_changed = true;
rezzexp = in_rezexp;
can_rez = true;
rez_experience = in_rezexp;
can_corpse_be_rezzed = true;
is_player_corpse = true;
is_locked = false;
being_looted_by = 0xFFFFFFFF;
@@ -279,13 +281,13 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
gold = 0;
platinum = 0;
strcpy(orgname, pp->name);
strcpy(corpse_name, pp->name);
strcpy(name, pp->name);
/* become_npc was not being initialized which led to some pretty funky things with newly created corpses */
become_npc = false;
SetPKItem(0);
SetPlayerKillItemID(0);
/* Check Rule to see if we can leave corpses */
if(!RuleB(Character, LeaveNakedCorpses) ||
@@ -335,9 +337,9 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
// this was mainly for client profile state reflection..should match db player inventory entries now.
iter_queue it;
for(it=client->GetInv().cursor_begin(),i=8001; it!=client->GetInv().cursor_end(); ++it,i++) {
for (it = client->GetInv().cursor_begin(), i = 8001; it != client->GetInv().cursor_end(); ++it, i++) {
item = *it;
if((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
if ((item && (!client->IsBecomeNPC())) || (item && client->IsBecomeNPC() && !item->GetItem()->NoRent)) {
std::list<uint32> slot_list = MoveItemToCorpse(client, item, i);
removed_list.merge(slot_list);
cursor = true;
@@ -346,16 +348,17 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
}
database.TransactionBegin();
if(removed_list.size() != 0) {
if (removed_list.size() != 0) {
std::stringstream ss("");
ss << "DELETE FROM inventory WHERE charid=" << client->CharacterID();
ss << " AND (";
std::list<uint32>::const_iterator iter = removed_list.begin();
bool first = true;
while(iter != removed_list.end()) {
if(first) {
while (iter != removed_list.end()) {
if (first) {
first = false;
} else {
}
else {
ss << " OR ";
}
ss << "slotid=" << (*iter);
@@ -365,8 +368,8 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob (
database.QueryDatabase(ss.str().c_str());
}
if(cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while(!client->GetInv().CursorEmpty())
if (cursor) { // all cursor items should be on corpse (client < SoF or RespawnFromHover = false)
while (!client->GetInv().CursorEmpty())
client->DeleteItemInInventory(MainCursor, 0, false, false);
}
else { // only visible cursor made it to corpse (client >= Sof and RespawnFromHover = true)
@@ -401,13 +404,13 @@ std::list<uint32> Corpse::MoveItemToCorpse(Client *client, ItemInst *item, int16
returnlist.push_back(equipslot);
// Qualified bag slot iterations. processing bag slots that don't exist is probably not a good idea.
if(item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
for(bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
if (item->IsType(ItemClassContainer) && ((equipslot >= EmuConstants::GENERAL_BEGIN && equipslot <= MainCursor))) {
for (bagindex = SUB_BEGIN; bagindex <= EmuConstants::ITEM_CONTAINER_SIZE; bagindex++) {
// For empty bags in cursor queue, slot was previously being resolved as SLOT_INVALID (-1)
interior_slot = Inventory::CalcSlotId(equipslot, bagindex);
interior_item = client->GetInv().GetItem(interior_slot);
if(interior_item) {
if (interior_item) {
AddItem(interior_item->GetItem()->ID, interior_item->GetCharges(), interior_slot, interior_item->GetAugmentItemID(0), interior_item->GetAugmentItemID(1), interior_item->GetAugmentItemID(2), interior_item->GetAugmentItemID(3), interior_item->GetAugmentItemID(4));
returnlist.push_back(Inventory::CalcSlotId(equipslot, bagindex));
client->DeleteItemInInventory(interior_slot, 0, true, false);
@@ -469,7 +472,7 @@ in_helmtexture,
0,
0),
corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)),
corpse_res_timer(RuleI(Character, CorpseResTimeMS)),
corpse_rez_timer(RuleI(Character, CorpseResTimeMS)),
corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)),
corpse_graveyard_timer(RuleI(Zone, GraveyardTimeMS)),
loot_cooldown_timer(10)
@@ -477,7 +480,7 @@ in_helmtexture,
LoadPlayerCorpseDecayTime(in_dbid);
if(!zone->HasGraveyard() || wasAtGraveyard)
if (!zone->HasGraveyard() || wasAtGraveyard)
corpse_graveyard_timer.Disable();
memset(item_tint, 0, sizeof(item_tint));
@@ -492,23 +495,25 @@ in_helmtexture,
itemlist = *in_itemlist;
in_itemlist->clear();
strcpy(orgname, in_charname);
strcpy(corpse_name, in_charname);
strcpy(name, in_charname);
this->copper = in_copper;
this->silver = in_silver;
this->gold = in_gold;
this->platinum = in_plat;
rezzexp = in_rezexp;
for (int i = 0; i < MAX_LOOTERS; i++)
rez_experience = in_rezexp;
for (int i = 0; i < MAX_LOOTERS; i++){
allowed_looters[i] = 0;
SetPKItem(0);
}
SetPlayerKillItemID(0);
}
Corpse::~Corpse() {
if (is_player_corpse && !(player_corpse_depop && corpse_db_id == 0)) {
Save();
Save();
}
ItemList::iterator cur,end;
cur = itemlist.begin();
@@ -562,7 +567,7 @@ bool Corpse::Save() {
dbpc->level = level;
dbpc->texture = this->texture;
dbpc->helmtexture = this->helmtexture;
dbpc->exp = rezzexp;
dbpc->exp = rez_experience;
memcpy(dbpc->item_tint, item_tint, sizeof(dbpc->item_tint));
dbpc->haircolor = haircolor;
@@ -581,17 +586,16 @@ bool Corpse::Save() {
end = itemlist.end();
for (; cur != end; ++cur) {
ServerLootItem_Struct* item = *cur;
item->equip_slot = ServerToCorpseSlot(item->equip_slot); // temp hack until corpse blobs are removed
memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(ServerLootItem_Struct));
}
/* Create New Corpse*/
if (corpse_db_id == 0) {
corpse_db_id = database.SaveCharacterCorpse(char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
}
/* Update Corpse Data */
else{
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, orgname, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
}
safe_delete_array(dbpc);
@@ -615,13 +619,13 @@ void Corpse::Bury() {
player_corpse_depop = true;
}
void Corpse::Depop() {
void Corpse::DepopNPCCorpse() {
if (IsNPCCorpse())
player_corpse_depop = true;
}
void Corpse::DepopCorpse() {
player_corpse_depop = true;
void Corpse::DepopPlayerCorpse() {
player_corpse_depop = true;
}
uint32 Corpse::CountItems() {
@@ -633,7 +637,9 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui
return;
is_corpse_changed = true;
ServerLootItem_Struct* item = new ServerLootItem_Struct;
memset(item, 0, sizeof(ServerLootItem_Struct));
item->item_id = itemnum;
item->charges = charges;
@@ -665,9 +671,9 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct**
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
for (; cur != end; ++cur) {
sitem2 = *cur;
if(sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) {
if (sitem2->equip_slot >= bagstart && sitem2->equip_slot < bagstart + 10) {
bag_item_data[sitem2->equip_slot - bagstart] = sitem2;
}
}
@@ -697,7 +703,7 @@ void Corpse::RemoveItem(uint16 lootslot) {
ItemList::iterator cur,end;
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
for (; cur != end; ++cur) {
ServerLootItem_Struct* sitem = *cur;
if (sitem->lootslot == lootslot) {
RemoveItem(sitem);
@@ -747,6 +753,7 @@ void Corpse::RemoveCash() {
bool Corpse::IsEmpty() const {
if (copper != 0 || silver != 0 || gold != 0 || platinum != 0)
return false;
return(itemlist.size() == 0);
}
@@ -754,8 +761,8 @@ bool Corpse::Process() {
if (player_corpse_depop)
return false;
if(corpse_delay_timer.Check()) {
for (int i=0; i<MAX_LOOTERS; i++)
if (corpse_delay_timer.Check()) {
for (int i = 0; i < MAX_LOOTERS; i++)
allowed_looters[i] = 0;
corpse_delay_timer.Disable();
return true;
@@ -787,18 +794,26 @@ bool Corpse::Process() {
corpse_res_timer.Disable();
}
*/
if(corpse_decay_timer.Check()) {
if(!RuleB(Zone, EnableShadowrest))
/* This is when a corpse hits decay timer and does checks*/
if (corpse_decay_timer.Check()) {
/* NPC */
if (IsNPCCorpse()){
corpse_decay_timer.Disable();
return false;
}
/* Client */
if (!RuleB(Zone, EnableShadowrest)){
Delete();
}
else {
if(database.BuryCharacterCorpse(corpse_db_id)) {
if (database.BuryCharacterCorpse(corpse_db_id)) {
Save();
player_corpse_depop = true;
corpse_db_id = 0;
LogFile->write(EQEMuLog::Debug, "Tagged %s player corpse has burried.", this->GetName());
}
else
{
else {
LogFile->write(EQEMuLog::Error, "Unable to bury %s player corpse.", this->GetName());
return true;
}
@@ -817,22 +832,21 @@ void Corpse::SetDecayTimer(uint32 decaytime) {
corpse_decay_timer.Start(decaytime);
}
bool Corpse::CanMobLoot(int charid) {
uint8 z=0;
for(int i=0; i<MAX_LOOTERS; i++) {
if(allowed_looters[i] != 0)
z++;
bool Corpse::CanPlayerLoot(int charid) {
uint8 looters = 0;
for (int i = 0; i < MAX_LOOTERS; i++) {
if (allowed_looters[i] != 0){
looters++;
}
if (allowed_looters[i] == charid)
return true;
}
if(z == 0)
return true;
else
return false;
/* If we have no looters, obviously client can loot */
return looters == 0;
}
void Corpse::AllowMobLoot(Mob *them, uint8 slot) {
void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) {
if(slot >= MAX_LOOTERS)
return;
if(them == nullptr || !them->IsClient())
@@ -863,31 +877,48 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
return;
}
if(being_looted_by == 0) { being_looted_by = 0xFFFFFFFF; }
if(being_looted_by == 0)
being_looted_by = 0xFFFFFFFF;
if(this->being_looted_by != 0xFFFFFFFF) {
// lets double check....
Entity* looter = entity_list.GetID(this->being_looted_by);
if(looter == 0) { this->being_looted_by = 0xFFFFFFFF; }
if(looter == 0)
this->being_looted_by = 0xFFFFFFFF;
}
uint8 tCanLoot = 1;
bool lootcoin = false;
if(database.GetVariable("LootCoin", tmp, 9)) { lootcoin = (atoi(tmp) == 1); }
uint8 Loot_Request_Type = 1;
bool loot_coin = false;
if(database.GetVariable("LootCoin", tmp, 9))
loot_coin = (atoi(tmp) == 1);
if(this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) {
SendLootReqErrorPacket(client, 0);
tCanLoot = 0;
Loot_Request_Type = 0;
}
else if (IsPlayerCorpse() && char_id == client->CharacterID()) {
Loot_Request_Type = 2;
}
else if ((IsNPCCorpse() || become_npc) && CanPlayerLoot(client->CharacterID())) {
Loot_Request_Type = 2;
}
else if (GetPlayerKillItem() == -1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot all items, variable cash */
Loot_Request_Type = 3;
}
else if (GetPlayerKillItem() == 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 item, variable cash */
Loot_Request_Type = 4;
}
else if (GetPlayerKillItem() > 1 && CanPlayerLoot(client->CharacterID())) { /* PVP loot 1 set item, variable cash */
Loot_Request_Type = 5;
}
else if(IsPlayerCorpse() && char_id == client->CharacterID()) { tCanLoot = 2; }
else if((IsNPCCorpse() || become_npc) && CanMobLoot(client->CharacterID())) { tCanLoot = 2; }
else if(GetPKItem() == -1 && CanMobLoot(client->CharacterID())) { tCanLoot = 3; } //pvp loot all items, variable cash
else if(GetPKItem() == 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 4; } //pvp loot 1 item, variable cash
else if(GetPKItem() > 1 && CanMobLoot(client->CharacterID())) { tCanLoot = 5; } //pvp loot 1 set item, variable cash
if(tCanLoot == 1) { if(client->Admin() < 100 || !client->GetGM()) { SendLootReqErrorPacket(client, 2); } }
if (Loot_Request_Type == 1) {
if (client->Admin() < 100 || !client->GetGM()) {
SendLootReqErrorPacket(client, 2);
}
}
if(tCanLoot >= 2 || (tCanLoot == 1 && client->Admin() >= 100 && client->GetGM())) {
if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) {
this->being_looted_by = client->GetID();
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct));
moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer;
@@ -895,8 +926,9 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
d->response = 1;
d->unknown1 = 0x42;
d->unknown2 = 0xef;
if(tCanLoot == 2 || (tCanLoot >= 3 && lootcoin)) { // dont take the coin off if it's a gm peeking at the corpse
/* Dont take the coin off if it's a gm peeking at the corpse */
if(Loot_Request_Type == 2 || (Loot_Request_Type >= 3 && loot_coin)) {
if(!IsPlayerCorpse() && client->IsGrouped() && client->AutoSplitEnabled() && client->GetGroup()) {
d->copper = 0;
d->silver = 0;
@@ -920,15 +952,15 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
outapp->priority = 6;
client->QueuePacket(outapp);
safe_delete(outapp);
if(tCanLoot == 5) {
int pkitem = GetPKItem();
if(Loot_Request_Type == 5) {
int pkitem = GetPlayerKillItem();
const Item_Struct* item = database.GetItem(pkitem);
ItemInst* inst = database.CreateItem(item, item->MaxCharges);
if(inst) {
client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
}
else { client->Message(13, "Could not find item number %i to send!!", GetPKItem()); }
else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); }
client->QueuePacket(app);
return;
@@ -940,8 +972,6 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
cur = itemlist.begin();
end = itemlist.end();
uint8 containercount = 0;
int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion());
for(; cur != end; ++cur) {
@@ -951,7 +981,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
// Dont display the item if it's in a bag
// Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse.
if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || tCanLoot>=3 ||
if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || Loot_Request_Type>=3 ||
(item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) {
if(i < corpselootlimit) {
item = database.GetItem(item_data->item_id);
@@ -981,14 +1011,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if(IsPlayerCorpse() && i == 0 && itemlist.size() > 0) { // somehow, player corpse contains items, but client doesn't see them...
client->Message(13, "This corpse contains items that are inaccessable!");
client->Message(15, "Contact a GM for item replacement, if necessary.");
client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetDBID(), GetName(), itemlist.size());
client->Message(15, "BUGGED CORPSE [DBID: %i, Name: %s, Item Count: %i]", GetCorpseDBID(), GetName(), itemlist.size());
cur = itemlist.begin();
end = itemlist.end();
for(; cur != end; ++cur) {
ServerLootItem_Struct* item_data = *cur;
item = database.GetItem(item_data->item_id);
LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
LogFile->write(EQEMuLog::Debug, "Corpse Looting: %s was not sent to client loot window (corpse_dbid: %i, charname: %s(%s))", item->Name, GetCorpseDBID(), client->GetName(), client->GetGM() ? "GM" : "Owner");
client->Message(0, "Inaccessable Corpse Item: %s", item->Name);
}
}
@@ -1034,7 +1064,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
SendEndLootErrorPacket(client);
return;
}
if (IsPlayerCorpse() && !CanMobLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) {
if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) {
client->Message(13, "Error: This is a player corpse and you dont own it.");
SendEndLootErrorPacket(client);
return;
@@ -1044,7 +1074,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
client->Message(13, "Error: Corpse locked by GM.");
return;
}
if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanMobLoot(client->CharacterID()) && GetPKItem() == 0){
if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){
client->Message(13, "Error: You cannot loot any more items from this corpse.");
SendEndLootErrorPacket(client);
being_looted_by = 0xFFFFFFFF;
@@ -1055,17 +1085,17 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10];
memset(bag_item_data, 0, sizeof(bag_item_data));
if (GetPKItem() > 1){
item = database.GetItem(GetPKItem());
if (GetPlayerKillItem() > 1){
item = database.GetItem(GetPlayerKillItem());
}
else if (GetPKItem() == -1 || GetPKItem() == 1){
else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){
item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward
}
else{
item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data);
}
if (GetPKItem()<=1 && item_data != 0) {
if (GetPlayerKillItem()<=1 && item_data != 0) {
item = database.GetItem(item_data->item_id);
}
@@ -1104,7 +1134,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
char buf[88];
char corpse_name[64];
strcpy(corpse_name, orgname);
strcpy(corpse_name, corpse_name);
snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name));
buf[87] = '\0';
std::vector<EQEmu::Any> args;
@@ -1149,7 +1179,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
}
/* Remove Bag Contents */
if (item->ItemClass == ItemClassContainer && (GetPKItem() != -1 || GetPKItem() != 1)) {
if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) {
for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) {
if (bag_item_data[i]) {
/* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */
@@ -1160,8 +1190,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) {
}
}
if (GetPKItem() != -1){
SetPKItem(0);
if (GetPlayerKillItem() != -1){
SetPlayerKillItemID(0);
}
/* Send message with item link to groups and such */
@@ -1211,7 +1241,6 @@ void Corpse::EndLoot(Client* client, const EQApplicationPacket* app) {
client->QueuePacket(outapp);
safe_delete(outapp);
//client->Save(); //inventory operations auto-commit
this->being_looted_by = 0xFFFFFFFF;
if (this->IsEmpty())
Delete();
@@ -1275,7 +1304,7 @@ void Corpse::QueryLoot(Client* to) {
}
if (IsPlayerCorpse()) {
to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetDBID());
to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetCorpseDBID());
}
else {
to->Message(0, "%i %s on %s.", y, y==1?"item":"items", this->GetName());
@@ -1330,8 +1359,8 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
return true;
}
void Corpse::CompleteRezz(){
rezzexp = 0;
void Corpse::CompleteResurrection(){
rez_experience = 0;
is_corpse_changed = true;
this->Save();
}
@@ -1375,7 +1404,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
}
void Corpse::AddLooter(Mob* who) {
for (int i=0; i<MAX_LOOTERS; i++) {
for (int i = 0; i < MAX_LOOTERS; i++) {
if (allowed_looters[i] == 0) {
allowed_looters[i] = who->CastToClient()->CharacterID();
break;
@@ -1400,111 +1429,5 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){
else {
corpse_graveyard_timer.SetTimer(3000);
}
}
/*
** Corpse slot translations are needed until corpse database blobs are converted
**
** To account for the addition of MainPowerSource, MainGeneral9 and MainGeneral10 into
** the contiguous possessions slot enumeration, the following designations will be used:
**
** Designatiom Server Corpse Offset
** --------------------------------------------------
** MainCharm 0 0 0
** ... ... ... 0
** MainWaist 20 20 0
** MainPowerSource 21 9999 +9978
** MainAmmo 22 21 -1
**
** MainGeneral1 23 22 -1
** ... ... ... -1
** MainGeneral8 30 29 -1
** MainGeneral9 31 9997 +9966
** MainGeneral10 32 9998 +9966
**
** MainCursor 33 30 -3
**
** MainGeneral1_1 251 251 0
** ... ... ... 0
** MainGeneral8_10 330 330 0
** MainGeneral9_1 331 341 +10
** ... ... ... +10
** MainGeneral10_10 350 360 +10
**
** MainCursor_1 351 331 -20
** ... ... ... -20
** MainCursor_10 360 340 -20
**
** (Not all slot designations are valid to all clients..see <client>##_constants.h files for valid slot enumerations)
*/
int16 Corpse::ServerToCorpseSlot(int16 server_slot)
{
return server_slot; // temporary return
/*
switch (server_slot)
{
case MainPowerSource:
return 9999;
case MainGeneral9:
return 9997;
case MainGeneral10:
return 9998;
case MainCursor:
return 30;
case MainAmmo:
case MainGeneral1:
case MainGeneral2:
case MainGeneral3:
case MainGeneral4:
case MainGeneral5:
case MainGeneral6:
case MainGeneral7:
case MainGeneral8:
return server_slot - 1;
default:
if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END)
return server_slot - 20;
else if (server_slot >= EmuConstants::GENERAL_BAGS_END - 19 && server_slot <= EmuConstants::GENERAL_BAGS_END)
return server_slot + 10;
else
return server_slot;
}
*/
}
int16 Corpse::CorpseToServerSlot(int16 corpse_slot)
{
return corpse_slot; // temporary return
/*
switch (corpse_slot)
{
case 9999:
return MainPowerSource;
case 9997:
return MainGeneral9;
case 9998:
return MainGeneral10;
case 30:
return MainCursor;
case 21: // old SLOT_AMMO
case 22: // old PERSONAL_BEGIN
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29: // old PERSONAL_END
return corpse_slot + 1;
default:
if (corpse_slot >= 331 && corpse_slot <= 340)
return corpse_slot + 20;
else if (corpse_slot >= 341 && corpse_slot <= 360)
return corpse_slot - 10;
else
return corpse_slot;
}
*/
}
+1676
View File
File diff suppressed because it is too large Load Diff
+77 -73
View File
@@ -27,7 +27,7 @@ class NPC;
#define MAX_LOOTERS 72
class Corpse : public Mob {
public:
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
@@ -35,114 +35,118 @@ public:
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const xyz_heading& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
//abstract virtual function implementations requird by base abstract class
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
void LoadPlayerCorpseDecayTime(uint32 dbid);
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
inline uint32 GetCorpseDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return corpse_name; }
bool IsEmpty() const;
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return is_player_corpse; }
bool IsNPCCorpse() const { return !is_player_corpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
virtual void DepopNPCCorpse();
virtual void DepopPlayerCorpse();
bool Process();
bool Save();
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetResTime() { if (!corpse_res_timer.Enabled()) return 0; else return corpse_res_timer.GetRemainingTime(); }
void CalcCorpseName();
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
inline uint32 GetDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return orgname;}
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); }
void SetDecayTimer(uint32 decay_time);
void SetDecayTimer(uint32 decaytime);
bool IsEmpty() const;
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0);
void Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
void QueryLoot(Client* to);
uint32 CountItems();
void Delete();
void Bury();
virtual void Depop();
virtual void DepopCorpse();
void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; }
int32 GetPlayerKillItem() { return player_kill_item; }
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0);
/* Corpse: Coin */
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
uint32 GetCopper() { return copper; }
uint32 GetSilver() { return silver; }
uint32 GetGold() { return gold; }
uint32 GetPlatinum() { return platinum; }
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
bool Summon(Client* client, bool spell, bool CheckDistance);
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteRezz();
void SetPKItem(int32 id) { player_kill_item = id; }
int32 GetPKItem() { return player_kill_item; }
bool CanMobLoot(int charid);
void AllowMobLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
/* Corpse: Resurrection */
bool IsRezzed() { return rez; }
void IsRezzed(bool in_rez) { rez = in_rez; }
void Spawn();
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteResurrection();
char orgname[64];
uint32 GetEquipment(uint8 material_slot) const; // returns item id
/* Corpse: Loot */
void QueryLoot(Client* to);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void AllowPlayerLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
uint32 CountItems();
bool CanPlayerLoot(int charid);
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
/* Mob */
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezzExp() { return rezzexp; }
// these are a temporary work-around until corpse inventory is removed from the database blob
static int16 ServerToCorpseSlot(int16 server_slot); // encode
static int16 CorpseToServerSlot(int16 corpse_slot); // decode
inline int GetRezExp() { return rez_experience; }
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
private:
bool is_player_corpse;
bool is_corpse_changed;
bool is_locked;
int32 player_kill_item;
uint32 corpse_db_id;
uint32 char_id;
ItemList itemlist;
bool is_player_corpse; /* Determines if Player Corpse or not */
bool is_corpse_changed; /* Determines if corpse has changed or not */
bool is_locked; /* Determines if corpse is locked */
int32 player_kill_item; /* Determines if Player Kill Item */
uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */
uint32 char_id; /* Character ID */
ItemList itemlist; /* Internal Item list used for corpses */
uint32 copper;
uint32 silver;
uint32 gold;
uint32 platinum;
bool player_corpse_depop;
uint32 being_looted_by;
uint32 rezzexp;
bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */
uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */
uint32 rez_experience; /* Amount of experience that the corpse would rez for */
bool rez;
bool can_rez;
bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */
bool become_npc;
int allowed_looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
Timer corpse_decay_timer;
Timer corpse_res_timer;
int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */
Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */
Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */
Timer corpse_delay_timer;
Timer corpse_graveyard_timer;
Timer loot_cooldown_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
};
#endif
+190
View File
@@ -0,0 +1,190 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CORPSE_H
#define CORPSE_H
#include "mob.h"
class Client;
class NPC;
#define MAX_LOOTERS 72
class Corpse : public Mob {
public:
static void SendEndLootErrorPacket(Client* client);
static void SendLootReqErrorPacket(Client* client, uint8 response = 2);
Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000);
Corpse(Client* client, int32 in_rezexp);
<<<<<<< HEAD
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const xyz_heading& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadFromDBData(uint32 in_dbid, uint32 in_charid, std::string in_charname, const xyz_heading& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
=======
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, float in_x, float in_y, float in_z, float in_heading, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
~Corpse();
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, float in_x, float in_y, float in_z, float in_heading, std::string time_of_death, bool rezzed, bool was_at_graveyard);
>>>>>>> master
/* Corpse: General */
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false,
<<<<<<< HEAD
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
void LoadPlayerCorpseDecayTime(uint32 dbid);
=======
bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) {
return false;
}
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
inline uint32 GetCorpseDBID() { return corpse_db_id; }
inline char* GetOwnerName() { return corpse_name; }
bool IsEmpty() const;
>>>>>>> master
bool IsCorpse() const { return true; }
bool IsPlayerCorpse() const { return is_player_corpse; }
bool IsNPCCorpse() const { return !is_player_corpse; }
bool IsBecomeNPCCorpse() const { return become_npc; }
virtual void DepopNPCCorpse();
virtual void DepopPlayerCorpse();
bool Process();
bool Save();
uint32 GetCharID() { return char_id; }
uint32 SetCharID(uint32 iCharID) { if (IsPlayerCorpse()) { return (char_id = iCharID); } return 0xFFFFFFFF; };
uint32 GetDecayTime() { if (!corpse_decay_timer.Enabled()) return 0xFFFFFFFF; else return corpse_decay_timer.GetRemainingTime(); }
uint32 GetRezTime() { if (!corpse_rez_timer.Enabled()) return 0; else return corpse_rez_timer.GetRemainingTime(); }
void SetDecayTimer(uint32 decay_time);
void Delete();
void Bury();
void CalcCorpseName();
void LoadPlayerCorpseDecayTime(uint32 dbid);
/* Corpse: Items */
uint32 GetWornItem(int16 equipSlot) const;
ServerLootItem_Struct* GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data = 0);
void SetPlayerKillItemID(int32 pk_item_id) { player_kill_item = pk_item_id; }
int32 GetPlayerKillItem() { return player_kill_item; }
void RemoveItem(uint16 lootslot);
void RemoveItem(ServerLootItem_Struct* item_data);
void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0);
/* Corpse: Coin */
void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum);
void RemoveCash();
uint32 GetCopper() { return copper; }
uint32 GetSilver() { return silver; }
uint32 GetGold() { return gold; }
uint32 GetPlatinum() { return platinum; }
/* Corpse: Resurrection */
bool IsRezzed() { return rez; }
void IsRezzed(bool in_rez) { rez = in_rez; }
void CastRezz(uint16 spellid, Mob* Caster);
void CompleteResurrection();
/* Corpse: Loot */
void QueryLoot(Client* to);
void LootItem(Client* client, const EQApplicationPacket* app);
void EndLoot(Client* client, const EQApplicationPacket* app);
void MakeLootRequestPackets(Client* client, const EQApplicationPacket* app);
void AllowPlayerLoot(Mob *them, uint8 slot);
void AddLooter(Mob *who);
uint32 CountItems();
bool CanPlayerLoot(int charid);
inline void Lock() { is_locked = true; }
inline void UnLock() { is_locked = false; }
inline bool IsLocked() { return is_locked; }
inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; }
inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); }
/* Mob */
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
bool Summon(Client* client, bool spell, bool CheckDistance);
void Spawn();
char corpse_name[64];
uint32 GetEquipment(uint8 material_slot) const;
uint32 GetEquipmentColor(uint8 material_slot) const;
inline int GetRezExp() { return rez_experience; }
protected:
std::list<uint32> MoveItemToCorpse(Client *client, ItemInst *item, int16 equipslot);
private:
<<<<<<< HEAD
bool is_player_corpse;
bool is_corpse_changed;
bool is_locked;
int32 player_kill_item;
uint32 corpse_db_id;
uint32 char_id;
ItemList itemlist;
uint32 copper;
=======
bool is_player_corpse; /* Determines if Player Corpse or not */
bool is_corpse_changed; /* Determines if corpse has changed or not */
bool is_locked; /* Determines if corpse is locked */
int32 player_kill_item; /* Determines if Player Kill Item */
uint32 corpse_db_id; /* Corpse Database ID (Player Corpse) */
uint32 char_id; /* Character ID */
ItemList itemlist; /* Internal Item list used for corpses */
uint32 copper;
>>>>>>> master
uint32 silver;
uint32 gold;
uint32 platinum;
bool player_corpse_depop; /* Sets up Corpse::Process to depop the player corpse */
uint32 being_looted_by; /* Determines what the corpse is being looted by internally for logic */
uint32 rez_experience; /* Amount of experience that the corpse would rez for */
bool rez;
bool can_corpse_be_rezzed; /* Bool declaring whether or not a corpse can be rezzed */
bool become_npc;
<<<<<<< HEAD
int allowed_looters[MAX_LOOTERS]; // People allowed to loot the corpse, character id
Timer corpse_decay_timer;
Timer corpse_res_timer;
Timer corpse_delay_timer;
=======
int allowed_looters[MAX_LOOTERS]; /* People allowed to loot the corpse, character id */
Timer corpse_decay_timer; /* The amount of time in millseconds in which a corpse will take to decay (Depop/Poof) */
Timer corpse_rez_timer; /* The amount of time in millseconds in which a corpse can be rezzed */
Timer corpse_delay_timer;
>>>>>>> master
Timer corpse_graveyard_timer;
Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */
Color_Struct item_tint[9];
};
#endif
+36 -54
View File
@@ -55,30 +55,25 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
else
value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration;
}
value += dmg*GetSpellFocusDMG()/100;
value += dmg*GetSpellFocusDMG()/100;
if (AI_HasSpellsEffects()){
int16 chance = 0;
int ratio = 0;
if (spells[spell_id].buffduration == 0) {
chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation;
if (chance && MakeRandomInt(1,100) <= chance){
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack;
value += (value*ratio)/100;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value));
}
}
else {
chance += spellbonuses.CriticalDoTChance;
if (chance && MakeRandomInt(1,100) <= chance){
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.DotCritDmgIncrease;
value += (value*ratio)/100;
}
@@ -119,14 +114,14 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100;
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio += MakeRandomInt(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) {
ratio += zone->random.Int(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
Critical = true;
}
@@ -193,22 +188,16 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalDotDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay);
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
if (chance > 0 && (MakeRandomInt(1, 100) <= chance)) {
if (chance > 0 && (zone->random.Roll(chance))) {
int32 ratio = 200;
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value = value_BaseEffect*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
GetFocusEffect(focusFcDamageAmt, spell_id);
@@ -216,7 +205,7 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
extra_dmg /= duration;
}
value -= extra_dmg;
@@ -224,25 +213,20 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
return value;
}
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
extra_dmg = target->GetFcDamageAmtIncoming(this, spell_id) +
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
GetFocusEffect(focusFcDamageAmt, spell_id);
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
extra_dmg /= duration;
}
value -= extra_dmg;
return value;
@@ -275,28 +259,26 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
//Scale all NPC spell healing via SetSpellFocusHeal(value)
value += value*GetSpellFocusHeal()/100;
value += value*GetSpellFocusHeal()/100;
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += value*target->GetHealRate(spell_id, this)/100;
}
//Allow for critical heal chance if NPC is loading spell effect bonuses.
if (AI_HasSpellsEffects()){
if(spells[spell_id].buffduration < 1) {
if(spellbonuses.CriticalHealChance && (MakeRandomInt(0,99) < spellbonuses.CriticalHealChance)) {
value = value*2;
if(spellbonuses.CriticalHealChance && (zone->random.Roll(spellbonuses.CriticalHealChance))) {
value = value*2;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value));
}
}
else if(spellbonuses.CriticalHealOverTime && (MakeRandomInt(0,99) < spellbonuses.CriticalHealOverTime)) {
value = value*2;
else if(spellbonuses.CriticalHealOverTime && (zone->random.Roll(spellbonuses.CriticalHealOverTime))) {
value = value*2;
}
}
return value;
}
@@ -326,7 +308,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && (zone->random.Roll(chance))) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@@ -360,7 +342,7 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && zone->random.Roll(chance))
return (value * 2);
}
@@ -374,12 +356,12 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
if (FrenziedDevastation && IsPureNukeSpell(spell_id))
cost *= 2;
cost *= 2;
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@@ -392,7 +374,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = MakeRandomInt(0, 100);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
@@ -444,7 +426,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
+1 -1
View File
@@ -1515,7 +1515,7 @@ XS(XS__ChooseRandom)
if (items < 1)
Perl_croak(aTHX_ "Usage: ChooseRandom(... list ...)");
int index = MakeRandomInt(0, items-1);
int index = zone->random.Int(0, items-1);
SV *tmp = ST(0);
ST(0) = ST(index);
+24 -27
View File
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
@@ -30,19 +29,16 @@
#include "../common/unix.h"
#endif
#include "net.h"
#include "masterentity.h"
#include "worldserver.h"
#include "../common/guilds.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/spdat.h"
#include "../common/features.h"
#include "string_ids.h"
#include "../common/guilds.h"
#include "../common/spdat.h"
#include "guild_mgr.h"
#include "raids.h"
#include "net.h"
#include "petitions.h"
#include "quest_parser_collection.h"
#include "raids.h"
#include "string_ids.h"
#include "worldserver.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -632,7 +628,7 @@ void EntityList::AddCorpse(Corpse *corpse, uint32 in_id)
void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
{
npc->SetID(GetFreeID());
npc->SetMerchantProbability((uint8) MakeRandomInt(0, 99));
npc->SetMerchantProbability((uint8) zone->random.Int(0, 99));
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
uint16 emoteid = npc->GetEmoteID();
@@ -662,10 +658,12 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
{
if (merc) {
if (merc)
{
merc->SetID(GetFreeID());
if (SendSpawnPacket) {
if (SendSpawnPacket)
{
if (dontqueue) {
// Send immediately
EQApplicationPacket *outapp = new EQApplicationPacket();
@@ -677,12 +675,10 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
// Queue the packet
NewSpawn_Struct *ns = new NewSpawn_Struct;
memset(ns, 0, sizeof(NewSpawn_Struct));
merc->FillSpawnStruct(ns, merc);
merc->FillSpawnStruct(ns, 0);
AddToSpawnQueue(merc->GetID(), &ns);
safe_delete(ns);
}
//parse->EventMERC(EVENT_SPAWN, merc, nullptr, "", 0);
}
merc_list.insert(std::pair<uint16, Merc *>(merc->GetID(), merc));
@@ -1573,7 +1569,7 @@ Client *EntityList::GetRandomClient(const xyz_location& location, float Distance
if (ClientsInRange.empty())
return nullptr;
return ClientsInRange[MakeRandomInt(0, ClientsInRange.size() - 1)];
return ClientsInRange[zone->random.Int(0, ClientsInRange.size() - 1)];
}
Corpse *EntityList::GetCorpseByOwner(Client *client)
@@ -1605,7 +1601,7 @@ Corpse *EntityList::GetCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid)
if (it->second->GetCorpseDBID() == dbid)
return it->second;
++it;
}
@@ -1659,7 +1655,7 @@ void EntityList::RemoveCorpseByDBID(uint32 dbid)
{
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetDBID() == dbid) {
if (it->second->GetCorpseDBID() == dbid) {
safe_delete(it->second);
free_ids.push(it->first);
it = corpse_list.erase(it);
@@ -1676,9 +1672,9 @@ int EntityList::RezzAllCorpsesByCharID(uint32 charid)
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->GetCharID() == charid) {
RezzExp += it->second->GetRezzExp();
RezzExp += it->second->GetRezExp();
it->second->IsRezzed(true);
it->second->CompleteRezz();
it->second->CompleteResurrection();
}
++it;
}
@@ -2654,7 +2650,7 @@ int32 EntityList::DeleteNPCCorpses()
auto it = corpse_list.begin();
while (it != corpse_list.end()) {
if (it->second->IsNPCCorpse()) {
it->second->Depop();
it->second->DepopNPCCorpse();
x++;
}
++it;
@@ -2893,7 +2889,7 @@ void EntityList::ClearFeignAggro(Mob *targ)
it->second->RemoveFromHateList(targ);
if (targ->IsClient()) {
if (it->second->GetLevel() >= 35 && MakeRandomInt(1, 100) <= 60)
if (it->second->GetLevel() >= 35 && zone->random.Roll(60))
it->second->AddFeignMemory(targ->CastToClient());
else
targ->CastToClient()->RemoveXTarget(it->second, false);
@@ -3640,7 +3636,8 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
NPC* n = it->second;
if (n->GetSwarmInfo()) {
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
n->CastToNPC()->hate_list.Add(other, 0, 0, bFrenzy);
if (!n->GetSpecialAbility(IMMUNE_AGGRO))
n->hate_list.Add(other, 0, 0, bFrenzy);
}
}
++it;
@@ -4499,7 +4496,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count)
selection.push_back(j);
while (selection.size() > 0 && count > 0) {
int k = MakeRandomInt(0, selection.size() - 1);
int k = zone->random.Int(0, selection.size() - 1);
counts[selection[k]]++;
count--;
selection.erase(selection.begin() + k);
@@ -4681,6 +4678,6 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range)
if(TargetsInRange.size() == 0)
return nullptr;
return TargetsInRange[MakeRandomInt(0, TargetsInRange.size() - 1)];
return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)];
}
+2 -2
View File
@@ -184,8 +184,8 @@ void Mob::CalculateNewFearpoint()
{
int ran = 250 - (loop*2);
loop++;
ranx = GetX()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
rany = GetY()+MakeRandomInt(0, ran-1)-MakeRandomInt(0, ran-1);
ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1);
ranz = FindGroundZ(ranx,rany);
if (ranz == -999999)
continue;
+26 -68
View File
@@ -15,75 +15,33 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
#include <stdlib.h>
#include <math.h>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "forage.h"
#include "entity.h"
#include "masterentity.h"
#include "npc.h"
#include "water_map.h"
#include "titles.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "entity.h"
#include "forage.h"
#include "npc.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "water_map.h"
#include "zonedb.h"
#include <iostream>
#ifdef _WINDOWS
#define snprintf _snprintf
#endif
#include "quest_parser_collection.h"
struct NPCType;
//max number of items which can be in the foraging table
//for a given zone.
#define FORAGE_ITEM_LIMIT 50
/*
The fishing and foraging need some work...
foraging currently gives each item an equal chance of dropping
fishing gives items which come in last from the select a very
very low chance of dropping.
Schema:
CREATE TABLE forage (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
PRIMARY KEY (id)
) TYPE=MyISAM;
old table upgrade:
alter table forage add chance smallint(6) NOT NULL default '0';
update forage set chance=100;
CREATE TABLE fishing (
id int(11) NOT NULL auto_increment,
zoneid int(4) NOT NULL default '0',
Itemid int(11) NOT NULL default '0',
skill_level smallint(6) NOT NULL default '0',
chance smallint(6) NOT NULL default '0',
npc_id int NOT NULL default 0,
npc_chance int NOT NULL default 0,
PRIMARY KEY (id)
) TYPE=MyISAM;
*/
// This allows EqEmu to have zone specific foraging - BoB
uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
uint32 item[FORAGE_ITEM_LIMIT];
@@ -125,7 +83,7 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
ret = 0;
uint32 rindex = MakeRandomInt(1, chancepool);
uint32 rindex = zone->random.Int(1, chancepool);
for(int i = 0; i < index; i++) {
if(rindex <= chance[i]) {
@@ -178,7 +136,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
if (index <= 0)
return 0;
uint32 random = MakeRandomInt(1, chancepool);
uint32 random = zone->random.Int(1, chancepool);
for (int i = 0; i < index; i++)
{
if (random > chance[i])
@@ -301,18 +259,18 @@ void Client::GoFish()
fishing_skill = 100+((fishing_skill-100)/2);
}
if (MakeRandomInt(0,175) < fishing_skill) {
if (zone->random.Int(0,175) < fishing_skill) {
uint32 food_id = 0;
//25% chance to fish an item.
if (MakeRandomInt(0, 399) <= fishing_skill ) {
if (zone->random.Int(0, 399) <= fishing_skill ) {
uint32 npc_id = 0;
uint8 npc_chance = 0;
food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);
//check for add NPC
if(npc_chance > 0 && npc_id) {
if(npc_chance < MakeRandomInt(0, 99)) {
if(npc_chance < zone->random.Int(0, 99)) {
const NPCType* tmp = database.GetNPCType(npc_id);
if(tmp != nullptr) {
auto positionNPC = GetPosition();
@@ -334,7 +292,7 @@ void Client::GoFish()
DeleteItemInInventory(bslot, 1, true); //do we need client update?
if(food_id == 0) {
int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1);
int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1);
food_id = common_fish_ids[index];
}
@@ -369,11 +327,11 @@ void Client::GoFish()
else
{
//chance to use bait when you dont catch anything...
if (MakeRandomInt(0, 4) == 1) {
if (zone->random.Int(0, 4) == 1) {
DeleteItemInInventory(bslot, 1, true); //do we need client update?
Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait!
} else {
if (MakeRandomInt(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line.
else
@@ -386,7 +344,7 @@ void Client::GoFish()
//chance to break fishing pole...
//this is potentially exploitable in that they can fish
//and then swap out items in primary slot... too lazy to fix right now
if (MakeRandomInt(0, 49) == 1) {
if (zone->random.Int(0, 49) == 1) {
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
DeleteItemInInventory(MainPrimary, 0, true);
}
@@ -415,18 +373,18 @@ void Client::ForageItem(bool guarantee) {
};
// these may need to be fine tuned, I am just guessing here
if (guarantee || MakeRandomInt(0,199) < skill_level) {
if (guarantee || zone->random.Int(0,199) < skill_level) {
uint32 foragedfood = 0;
uint32 stringid = FORAGE_NOEAT;
if (MakeRandomInt(0,99) <= 25) {
if (zone->random.Roll(25)) {
foragedfood = database.GetZoneForage(m_pp.zone_id, skill_level);
}
//not an else in case theres no DB food
if(foragedfood == 0) {
uint8 index = 0;
index = MakeRandomInt(0, MAX_COMMON_FOOD_IDS-1);
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
foragedfood = common_food_ids[index];
}
@@ -483,7 +441,7 @@ void Client::ForageItem(bool guarantee) {
}
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) {
if(!guarantee && zone->random.Roll(ChanceSecondForage)) {
Message_StringID(MT_Skills, FORAGE_MASTERY);
ForageItem(true);
}
+30 -14
View File
@@ -592,12 +592,15 @@ bool Group::DelMemberOOZ(const char *Name) {
bool Group::DelMember(Mob* oldmember,bool ignoresender)
{
if (oldmember == nullptr){
if (oldmember == nullptr)
{
return false;
}
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (members[i] == oldmember) {
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
{
if (members[i] == oldmember)
{
members[i] = nullptr;
membername[i][0] = '\0';
memset(membername[i],0,64);
@@ -606,16 +609,6 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
}
}
//handle leader quitting group gracefully
if (oldmember == GetLeader() && GroupCount() >= 2) {
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) {
if(members[nl]) {
ChangeLeader(members[nl]);
break;
}
}
}
/* This may seem pointless but the case above does not cover the following situation:
* Group has Leader a, member b, member c
* b and c are out of zone
@@ -624,10 +617,33 @@ bool Group::DelMember(Mob* oldmember,bool ignoresender)
* a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b)
* Ultimately we should think up a better solution to this.
*/
if(oldmember == GetLeader()) {
if(oldmember == GetLeader())
{
SetLeader(nullptr);
}
//handle leader quitting group gracefully
if (oldmember == GetLeader() && GroupCount() >= 2)
{
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++)
{
if(members[nl])
{
if (members[nl]->IsClient())
{
ChangeLeader(members[nl]);
break;
}
}
}
}
if (GetLeader() == nullptr)
{
DisbandGroup();
return true;
}
ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct));
ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer;
gl->gid = GetID();
+3 -13
View File
@@ -15,23 +15,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "../common/database.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/string_util.h"
#include "guild_mgr.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "worldserver.h"
extern WorldServer worldserver;
+1 -1
View File
@@ -487,7 +487,7 @@ Mob *HateList::GetRandom()
}
auto iterator = list.begin();
int random = MakeRandomInt(0, count - 1);
int random = zone->random.Int(0, count - 1);
for (int i = 0; i < random; i++)
++iterator;
+10 -15
View File
@@ -15,24 +15,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "zonedb.h"
#include "../common/spdat.h"
#include "../common/packet_dump.h"
#include "../common/packet_functions.h"
#include "petitions.h"
#include "../common/serverinfo.h"
#include "../common/zone_numbers.h"
#include "../common/moremath.h"
#include "../common/guilds.h"
#include "../common/logsys.h"
#include "../common/string_util.h"
#include "string_ids.h"
#include "npc_ai.h"
#include "quest_parser_collection.h"
#include "worldserver.h"
#include "zonedb.h"
extern WorldServer worldserver;
// @merth: this needs to be touched up
@@ -199,7 +189,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) {
return (m_inv.HasItemByLoreGroup(item->LoreGroup, ~invWhereSharedBank) != INVALID_INDEX);
}
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) {
bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile) {
this->EVENT_ITEM_ScriptStopReturn();
// TODO: update calling methods and script apis to handle a failure return
@@ -557,6 +547,11 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// attune item
if(attuned && inst->GetItem()->Attuneable)
inst->SetInstNoDrop(true);
if(ornament_icon > 0 && ornament_idfile > 0) {
inst->SetOrnamentIcon(ornament_icon);
inst->SetOrnamentationIDFile(ornament_idfile);
}
// check to see if item is usable in requested slot
if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) {
+9 -8
View File
@@ -22,6 +22,7 @@
#include "npc.h"
#include "masterentity.h"
#include "zonedb.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -48,15 +49,15 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
if (lts->mincash == lts->maxcash)
cash = lts->mincash;
else
cash = MakeRandomInt(lts->mincash, lts->maxcash);
cash = zone->random.Int(lts->mincash, lts->maxcash);
if (cash != 0) {
if (lts->avgcoin != 0) {
//this is some crazy ass stuff... and makes very little sense... dont use it, k?
uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
*copper = MakeRandomInt(mincoin, maxcoin);
*silver = MakeRandomInt(mincoin, maxcoin);
*gold = MakeRandomInt(mincoin, maxcoin);
*copper = zone->random.Int(mincoin, maxcoin);
*silver = zone->random.Int(mincoin, maxcoin);
*gold = zone->random.Int(mincoin, maxcoin);
if(*copper > cash) { *copper = cash; }
cash -= *copper;
if(*silver>(cash/10)) { *silver = (cash/10); }
@@ -91,7 +92,7 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
float drop_chance = 0.0f;
if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = MakeRandomFloat(0.0, 100.0);
drop_chance = zone->random.Real(0.0, 100.0);
}
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
@@ -117,7 +118,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
uint8 limit = 0;
// Start at a random point in itemlist.
uint32 item = MakeRandomInt(0, lds->NumEntries-1);
uint32 item = zone->random.Int(0, lds->NumEntries-1);
// Main loop.
for (uint32 i=0; i<lds->NumEntries;)
{
@@ -136,7 +137,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
float drop_chance = 0.0;
if(thischance != 100.0)
drop_chance = MakeRandomFloat(0.0, 100.0);
drop_chance = zone->random.Real(0.0, 100.0);
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
@@ -281,7 +282,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
eslot = MaterialPrimary;
}
else if (foundslot == MainSecondary
&& (GetOwner() != nullptr || (GetLevel() >= 13 && MakeRandomInt(0,99) < NPC_DW_CHANCE) || (item2->Damage==0)) &&
&& (GetOwner() != nullptr || (GetLevel() >= 13 && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) &&
(item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield ||
item2->ItemType == ItemType1HPiercing))
{
+3 -3
View File
@@ -39,7 +39,7 @@ void Lua_Corpse::ResetLooter() {
uint32 Lua_Corpse::GetDBID() {
Lua_Safe_Call_Int();
return self->GetDBID();
return self->GetCorpseDBID();
}
bool Lua_Corpse::IsRezzed() {
@@ -114,12 +114,12 @@ void Lua_Corpse::SetDecayTimer(uint32 decaytime) {
bool Lua_Corpse::CanMobLoot(int charid) {
Lua_Safe_Call_Bool();
return self->CanMobLoot(charid);
return self->CanPlayerLoot(charid);
}
void Lua_Corpse::AllowMobLoot(Lua_Mob them, uint8 slot) {
Lua_Safe_Call_Void();
self->AllowMobLoot(them, slot);
self->AllowPlayerLoot(them, slot);
}
bool Lua_Corpse::Summon(Lua_Client client, bool spell, bool checkdistance) {
+129 -181
View File
@@ -62,7 +62,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,GetLevel());
}
GetMercSize();
size = d->size;
CalcBonuses();
SetHP(GetMaxHP());
@@ -112,131 +112,66 @@ void Merc::CalcBonuses()
rooted = FindType(SE_Root);
}
void Merc::GetMercSize() {
float Merc::GetDefaultSize() {
float MercSize = GetSize();
switch(this->GetRace()) {
case 1: // Humans have no race bonus
break;
case 2: // Barbarian
MercSize = 7.0;
break;
case 3: // Erudite
break;
case 4: // Wood Elf
MercSize = 5.0;
break;
case 5: // High Elf
break;
case 6: // Dark Elf
MercSize = 5.0;
break;
case 7: // Half Elf
MercSize = 5.5;
break;
case 8: // Dwarf
MercSize = 4.0;
break;
case 9: // Troll
MercSize = 8.0;
break;
case 10: // Ogre
MercSize = 9.0;
break;
case 11: // Halfling
MercSize = 3.5;
break;
case 12: // Gnome
MercSize = 3.0;
break;
case 128: // Iksar
break;
case 130: // Vah Shir
MercSize = 7.0;
break;
case 330: // Froglok
MercSize = 5.0;
break;
case 522: // Drakkin
MercSize = 5.0;
break;
switch(this->GetRace())
{
case 1: // Humans
MercSize = 6.0;
break;
case 2: // Barbarian
MercSize = 7.0;
break;
case 3: // Erudite
MercSize = 6.0;
break;
case 4: // Wood Elf
MercSize = 5.0;
break;
case 5: // High Elf
MercSize = 6.0;
break;
case 6: // Dark Elf
MercSize = 5.0;
break;
case 7: // Half Elf
MercSize = 5.5;
break;
case 8: // Dwarf
MercSize = 4.0;
break;
case 9: // Troll
MercSize = 8.0;
break;
case 10: // Ogre
MercSize = 9.0;
break;
case 11: // Halfling
MercSize = 3.5;
break;
case 12: // Gnome
MercSize = 3.0;
break;
case 128: // Iksar
MercSize = 6.0;
break;
case 130: // Vah Shir
MercSize = 7.0;
break;
case 330: // Froglok
MercSize = 5.0;
break;
case 522: // Drakkin
MercSize = 5.0;
break;
default:
MercSize = 6.0;
break;
}
this->size = MercSize;
}
void Merc::GenerateAppearance() {
// Randomize facial appearance
int iFace = 0;
if(this->GetRace() == 2) { // Barbarian w/Tatoo
iFace = MakeRandomInt(0, 79);
}
else {
iFace = MakeRandomInt(0, 7);
}
int iHair = 0;
int iBeard = 0;
int iBeardColor = 1;
if(this->GetRace() == 522) {
iHair = MakeRandomInt(0, 8);
iBeard = MakeRandomInt(0, 11);
iBeardColor = MakeRandomInt(0, 3);
}
else if(this->GetGender()) {
iHair = MakeRandomInt(0, 2);
if(this->GetRace() == 8) { // Dwarven Females can have a beard
if(MakeRandomInt(1, 100) < 50) {
iFace += 10;
}
}
}
else {
iHair = MakeRandomInt(0, 3);
iBeard = MakeRandomInt(0, 5);
iBeardColor = MakeRandomInt(0, 19);
}
int iHairColor = 0;
if(this->GetRace() == 522) {
iHairColor = MakeRandomInt(0, 3);
}
else {
iHairColor = MakeRandomInt(0, 19);
}
uint8 iEyeColor1 = (uint8)MakeRandomInt(0, 9);
uint8 iEyeColor2 = 0;
if(this->GetRace() == 522) {
iEyeColor1 = iEyeColor2 = (uint8)MakeRandomInt(0, 11);
}
else if(MakeRandomInt(1, 100) > 96) {
iEyeColor2 = MakeRandomInt(0, 9);
}
else {
iEyeColor2 = iEyeColor1;
}
int iHeritage = 0;
int iTattoo = 0;
int iDetails = 0;
if(this->GetRace() == 522) {
iHeritage = MakeRandomInt(0, 6);
iTattoo = MakeRandomInt(0, 7);
iDetails = MakeRandomInt(0, 7);
}
this->luclinface = iFace;
this->hairstyle = iHair;
this->beard = iBeard;
this->beardcolor = iBeardColor;
this->haircolor = iHairColor;
this->eyecolor1 = iEyeColor1;
this->eyecolor2 = iEyeColor2;
this->drakkin_heritage = iHeritage;
this->drakkin_tattoo = iTattoo;
this->drakkin_details = iDetails;
return MercSize;
}
int Merc::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
@@ -1258,7 +1193,6 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.guildrank = 0;
ns->spawn.showhelm = 1;
ns->spawn.flymode = 0;
ns->spawn.size = 0;
ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse
ns->spawn.IsMercenary = 1;
@@ -1523,7 +1457,7 @@ void Merc::AI_Process() {
meleeDistance = meleeDistance * .30;
}
else {
meleeDistance *= (float)MakeRandomFloat(.50, .85);
meleeDistance *= (float)zone->random.Real(.50, .85);
}
if(IsMercCaster() && GetLevel() > 12) {
if(IsMercCasterCombatRange(GetTarget()))
@@ -1624,7 +1558,7 @@ void Merc::AI_Process() {
if (GetTarget() && flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Roll(flurrychance))
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@@ -1635,7 +1569,7 @@ void Merc::AI_Process() {
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
if (GetTarget() && ExtraAttackChanceBonus) {
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Roll(ExtraAttackChanceBonus))
{
Attack(GetTarget(), MainPrimary, false);
}
@@ -1669,10 +1603,8 @@ void Merc::AI_Process() {
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
float random = MakeRandomFloat(0, 1);
// Max 78% of DW
if (random < DualWieldProbability)
if (zone->random.Roll(DualWieldProbability))
{
Attack(GetTarget(), MainSecondary); // Single attack with offhand
@@ -1934,7 +1866,7 @@ bool EntityList::Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance,
return false;
if (iChance < 100) {
int8 tmp = MakeRandomInt(1, 100);
int8 tmp = zone->random.Int(1, 100);
if (tmp > iChance)
return false;
}
@@ -2030,7 +1962,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) > iChance){
if (zone->random.Int(0, 100) > iChance){
return false;
}
}
@@ -2315,14 +2247,14 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
if(selectedMercSpell.spellid == 0 && !tar->GetSpecialAbility(UNSTUNABLE) && !tar->IsStunned()) {
uint8 stunChance = 15;
if(MakeRandomInt(1, 100) <= stunChance) {
if(zone->random.Roll(stunChance)) {
selectedMercSpell = GetBestMercSpellForStun(this);
}
}
if(selectedMercSpell.spellid == 0) {
uint8 lureChance = 25;
if(MakeRandomInt(1, 100) <= lureChance) {
if(zone->random.Roll(lureChance)) {
selectedMercSpell = GetBestMercSpellForNukeByTargetResists(this, tar);
}
}
@@ -2742,14 +2674,14 @@ int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
if (MakeRandomInt(1,100) <= chance){
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (MakeRandomInt(1,100) <= RuleI(Spells, WizCritChance))) {
ratio = MakeRandomInt(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) {
ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
Critical = true;
}
@@ -2833,7 +2765,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
if(chance && zone->random.Roll(chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
@@ -2864,7 +2796,7 @@ int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
if(chance && zone->random.Roll(chance))
return (value * 2);
}
@@ -2876,7 +2808,7 @@ int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{
int16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
@@ -2893,7 +2825,7 @@ int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
if(focus_redux > 0)
{
PercentManaReduction += MakeRandomFloat(1, (double)focus_redux);
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
@@ -3825,17 +3757,17 @@ MercSpell Merc::GetBestMercSpellForAENuke(Merc* caster, Mob* tar) {
}
//check of we even want to cast an AE nuke
if(MakeRandomInt(1, 100) <= initialCastChance) {
if(zone->random.Roll(initialCastChance)) {
result = GetBestMercSpellForAERainNuke(caster, tar);
//check if we have a spell & allow for other AE nuke types
if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) {
if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) {
result = GetBestMercSpellForPBAENuke(caster, tar);
//check if we have a spell & allow for other AE nuke types
if(result.spellid == 0 && MakeRandomInt(1, 100) <= castChanceFalloff) {
if(result.spellid == 0 && zone->random.Roll(castChanceFalloff)) {
result = GetBestMercSpellForTargetedAENuke(caster, tar);
}
@@ -3879,7 +3811,7 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) {
&& !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@@ -3929,7 +3861,7 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) {
if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, caster, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && MakeRandomInt(1, 100) <= castChance) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@@ -3976,7 +3908,7 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) {
for(std::list<MercSpell>::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAERainNukeSpell(mercSpellListItr->spellid) && MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck) {
@@ -4015,7 +3947,7 @@ MercSpell Merc::GetBestMercSpellForNuke(Merc* caster) {
for(std::list<MercSpell>::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsPureNukeSpell(mercSpellListItr->spellid) && !IsAENukeSpell(mercSpellListItr->spellid)
&& MakeRandomInt(1, 100) <= castChance && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
&& zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
@@ -4447,7 +4379,7 @@ bool Merc::CheckConfidence() {
ConfidenceLossChance = 25 - ( 5 * (GetTierID() - 1));
}
if(MakeRandomInt(0 ,100) < ConfidenceLossChance) {
if(zone->random.Roll(ConfidenceLossChance)) {
result = false;
}
@@ -4593,7 +4525,7 @@ void Merc::DoClassAttacks(Mob *target) {
break;
case TANK:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
if(MakeRandomInt(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
{
DoAnim(animKick);
int32 dmg = 0;
@@ -4606,7 +4538,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetKickDamage();
else
dmg = MakeRandomInt(1, GetKickDamage());
dmg = zone->random.Int(1, GetKickDamage());
}
}
@@ -4628,7 +4560,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(RuleB(Combat, UseIntervalAC))
dmg = GetBashDamage();
else
dmg = MakeRandomInt(1, GetBashDamage());
dmg = zone->random.Int(1, GetBashDamage());
}
}
@@ -4756,7 +4688,7 @@ const char* Merc::GetRandomName(){
bool valid = false;
while(!valid) {
int rndnum=MakeRandomInt(0, 75),n=1;
int rndnum=zone->random.Int(0, 75),n=1;
bool dlc=false;
bool vwl=false;
bool dbl=false;
@@ -4777,18 +4709,18 @@ const char* Merc::GetRandomName(){
rndname[0]=vowels[rndnum];
vwl=true;
}
int namlen=MakeRandomInt(5, 10);
int namlen=zone->random.Int(5, 10);
for (int i=n;i<namlen;i++)
{
dlc=false;
if (vwl) //last char was a vowel
{ // so pick a cons or cons pair
rndnum=MakeRandomInt(0, 62);
rndnum=zone->random.Int(0, 62);
if (rndnum>46)
{ // pick a cons pair
if (i>namlen-3) // last 2 chars in name?
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
rndnum=MakeRandomInt(0, 7)*2;
rndnum=zone->random.Int(0, 7)*2;
}
else
{ // pick any from the set
@@ -4806,12 +4738,12 @@ const char* Merc::GetRandomName(){
}
else
{ // select a vowel
rndname[i]=vowels[MakeRandomInt(0, 16)];
rndname[i]=vowels[zone->random.Int(0, 16)];
}
vwl=!vwl;
if (!dbl && !dlc)
{ // one chance at double letters in name
if (!MakeRandomInt(0, i+9)) // chances decrease towards end of name
if (!zone->random.Int(0, i+9)) // chances decrease towards end of name
{
rndname[i+1]=rndname[i];
dbl=true;
@@ -4940,22 +4872,37 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
}
snprintf(npc_type->name, 64, "%s", c->GetMercInfo().merc_name);
}
uint8 gender = 0;
if(merchant_id > 0) {
npc_type->race = merc_template->RaceID;
// Use the Gender and Size of the Merchant if possible
uint8 tmpgender = 0;
float tmpsize = 6.0f;
if(merchant_id > 0)
{
NPC* tar = entity_list.GetNPCByID(merchant_id);
if(tar) {
gender = Mob::GetDefaultGender(npc_type->race, tar->GetGender());
if(tar)
{
tmpgender = tar->GetGender();
tmpsize = tar->GetSize();
}
else
{
tmpgender = Mob::GetDefaultGender(npc_type->race, c->GetMercInfo().Gender);
}
}
else {
gender = c->GetMercInfo().Gender;
else
{
tmpgender = c->GetMercInfo().Gender;
tmpsize = c->GetMercInfo().MercSize;
}
sprintf(npc_type->lastname, "%s's %s", c->GetName(), "Mercenary");
npc_type->gender = gender;
sprintf(npc_type->lastname, "%s's Mercenary", c->GetName());
npc_type->gender = tmpgender;
npc_type->size = tmpsize;
npc_type->loottable_id = 0; // Loottable has to be 0, otherwise we'll be leavin' some corpses!
npc_type->npc_id = 0; //NPC ID has to be 0, otherwise db gets all confuzzled.
npc_type->race = merc_template->RaceID;
npc_type->class_ = merc_template->ClassID;
npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed.
@@ -4975,6 +4922,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
snprintf(merc->name, 64, "%s", c->GetMercInfo().merc_name);
merc->SetSuspended(c->GetMercInfo().IsSuspended);
merc->gender = c->GetMercInfo().Gender;
merc->size = c->GetMercInfo().MercSize;
merc->SetHP(c->GetMercInfo().hp <= 0 ? merc->GetMaxHP() : c->GetMercInfo().hp);
merc->SetMana(c->GetMercInfo().hp <= 0 ? merc->GetMaxMana() : c->GetMercInfo().mana);
merc->SetEndurance(c->GetMercInfo().endurance);
@@ -4989,6 +4937,11 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
merc->drakkin_tattoo = c->GetMercInfo().drakkinTattoo;
merc->drakkin_details = c->GetMercInfo().drakkinDetails;
}
else
{
// Give Random Features to newly hired Mercs
merc->RandomizeFeatures(false, true);
}
if(merc->GetMercID()) {
database.LoadMercBuffs(merc);
@@ -5008,7 +4961,8 @@ void Merc::UpdateMercInfo(Client *c) {
snprintf(c->GetMercInfo().merc_name, 64, "%s", name);
c->GetMercInfo().mercid = GetMercID();
c->GetMercInfo().IsSuspended = IsSuspended();
c->GetMercInfo().Gender = gender;
c->GetMercInfo().Gender = GetGender();
c->GetMercInfo().MercSize = GetSize();
c->GetMercInfo().hp = GetHP();
c->GetMercInfo().mana = GetMana();
c->GetMercInfo().endurance = GetEndurance();
@@ -5540,7 +5494,7 @@ void Client::SpawnMercOnZone() {
}
else
{
int32 TimeDiff = GetMercInfo().SuspendedTime + RuleI(Mercs, SuspendIntervalS) - time(nullptr);
int32 TimeDiff = GetMercInfo().SuspendedTime - time(nullptr);
if (TimeDiff > 0)
{
if (!GetPTimers().Enabled(pTimerMercSuspend))
@@ -5558,6 +5512,11 @@ void Client::SpawnMercOnZone() {
Message(7, "Mercenary Debug: SpawnMercOnZone Suspended Merc.");
}
}
else
{
// No Merc Hired
SendClearMercInfo();
}
}
void Client::SendMercTimer(Merc* merc) {
@@ -5604,9 +5563,6 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
SetMerc(merc);
merc->Unsuspend(setMaxStats);
merc->SetStance(GetMercInfo().Stance);
GetMercInfo().SuspendedTime = 0;
//SendMercTimer(merc);
if (MERC_DEBUG > 0)
Message(7, "Mercenary Debug: SpawnMerc Success.");
@@ -5666,7 +5622,6 @@ bool Client::MercOnlyOrNoGroup() {
bool Merc::Unsuspend(bool setMaxStats) {
Client* mercOwner = nullptr;
bool loaded = false;
if(GetMercOwner()) {
mercOwner = GetMercOwner();
@@ -5694,12 +5649,8 @@ bool Merc::Unsuspend(bool setMaxStats) {
if(!mercOwner->GetPTimers().Expired(&database, pTimerMercSuspend, false))
mercOwner->GetPTimers().Clear(&database, pTimerMercSuspend);
MercJoinClientGroup();
if(loaded)
if (MercJoinClientGroup())
{
LoadMercSpells();
if(setMaxStats)
{
SetHP(GetMaxHP());
@@ -5977,7 +5928,7 @@ Merc* Client::GetMerc() {
if(GetMercID() == 0)
{
if (MERC_DEBUG > 0)
//Message(7, "Mercenary Debug: GetMerc 0.");
Message(7, "Mercenary Debug: GetMerc 0.");
return (nullptr);
}
@@ -5998,9 +5949,6 @@ Merc* Client::GetMerc() {
return (nullptr);
}
if (MERC_DEBUG > 0)
//Message(7, "Mercenary Debug: GetMerc Success.");
return (tmp);
}
@@ -6073,7 +6021,7 @@ void Client::SetMerc(Merc* newmerc) {
GetMercInfo().IsSuspended = newmerc->IsSuspended();
GetMercInfo().SuspendedTime = 0;
GetMercInfo().Gender = newmerc->GetGender();
//GetMercInfo().State = newmerc->GetStance();
GetMercInfo().State = newmerc->IsSuspended() ? MERC_STATE_SUSPENDED : MERC_STATE_NORMAL;
snprintf(GetMercInfo().merc_name, 64, "%s", newmerc->GetName());
if (MERC_DEBUG > 0)
Message(7, "Mercenary Debug: SetMerc New Merc.");
+6329
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -332,9 +332,7 @@ private:
int GroupLeadershipAAHealthRegeneration();
int GroupLeadershipAAOffenseEnhancement();
void GetMercSize();
void GenerateAppearance();
float GetDefaultSize();
bool LoadMercSpells();
bool CheckStance(int16 stance);
+434 -240
View File
@@ -15,17 +15,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "masterentity.h"
#include "../common/spdat.h"
#include "string_ids.h"
#include "worldserver.h"
#include "quest_parser_collection.h"
#include "../common/string_util.h"
#include <sstream>
#include <math.h>
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include <limits.h>
#include <math.h>
#include <sstream>
extern EntityList entity_list;
@@ -260,13 +260,24 @@ Mob::Mob(const char* in_name,
casting_spell_inventory_slot = 0;
target = 0;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_spell_id[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_target_id[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_increment[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_x[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_y[i] = 0; }
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_z[i] = 0; }
projectile_timer.Disable();
ActiveProjectileATK = false;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++)
{
ProjectileAtk[i].increment = 0;
ProjectileAtk[i].hit_increment = 0;
ProjectileAtk[i].target_id = 0;
ProjectileAtk[i].wpn_dmg = 0;
ProjectileAtk[i].origin_x = 0.0f;
ProjectileAtk[i].origin_y = 0.0f;
ProjectileAtk[i].origin_z = 0.0f;
ProjectileAtk[i].tlast_x = 0.0f;
ProjectileAtk[i].tlast_y = 0.0f;
ProjectileAtk[i].ranged_id = 0;
ProjectileAtk[i].ammo_id = 0;
ProjectileAtk[i].ammo_slot = 0;
ProjectileAtk[i].skill = 0;
ProjectileAtk[i].speed_mod = 0.0f;
}
memset(&itembonuses, 0, sizeof(StatBonuses));
memset(&spellbonuses, 0, sizeof(StatBonuses));
@@ -702,7 +713,8 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) {
NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer;
FillSpawnStruct(ns, ForWho);
if(strlen(ns->spawn.lastName) == 0) {
if(strlen(ns->spawn.lastName) == 0)
{
switch(ns->spawn.class_)
{
case TRIBUTE_MASTER:
@@ -780,70 +792,78 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) {
// Custom packet data
NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer;
strcpy(ns2->spawn.name, ns->spawn.name);
switch(ns->spawn.class_)
{
case TRIBUTE_MASTER:
strcpy(ns2->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns2->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns2->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns->spawn.lastName,"Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns2->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns2->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns2->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns2->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns2->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns2->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns2->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns2->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns2->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns2->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns2->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns2->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns2->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns2->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns->spawn.lastName, "Mercenary Recruiter");
break;
default:
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
break;
}
// Set default Last Names for certain Classes if not defined
if (strlen(ns->spawn.lastName) == 0)
{
switch (ns->spawn.class_)
{
case TRIBUTE_MASTER:
strcpy(ns2->spawn.lastName, "Tribute Master");
break;
case ADVENTURERECRUITER:
strcpy(ns2->spawn.lastName, "Adventure Recruiter");
break;
case BANKER:
strcpy(ns2->spawn.lastName, "Banker");
break;
case ADVENTUREMERCHANT:
strcpy(ns2->spawn.lastName, "Adventure Merchant");
break;
case WARRIORGM:
strcpy(ns2->spawn.lastName, "GM Warrior");
break;
case PALADINGM:
strcpy(ns2->spawn.lastName, "GM Paladin");
break;
case RANGERGM:
strcpy(ns2->spawn.lastName, "GM Ranger");
break;
case SHADOWKNIGHTGM:
strcpy(ns2->spawn.lastName, "GM Shadowknight");
break;
case DRUIDGM:
strcpy(ns2->spawn.lastName, "GM Druid");
break;
case BARDGM:
strcpy(ns2->spawn.lastName, "GM Bard");
break;
case ROGUEGM:
strcpy(ns2->spawn.lastName, "GM Rogue");
break;
case SHAMANGM:
strcpy(ns2->spawn.lastName, "GM Shaman");
break;
case NECROMANCERGM:
strcpy(ns2->spawn.lastName, "GM Necromancer");
break;
case WIZARDGM:
strcpy(ns2->spawn.lastName, "GM Wizard");
break;
case MAGICIANGM:
strcpy(ns2->spawn.lastName, "GM Magician");
break;
case ENCHANTERGM:
strcpy(ns2->spawn.lastName, "GM Enchanter");
break;
case BEASTLORDGM:
strcpy(ns2->spawn.lastName, "GM Beastlord");
break;
case BERSERKERGM:
strcpy(ns2->spawn.lastName, "GM Berserker");
break;
case MERCERNARY_MASTER:
strcpy(ns2->spawn.lastName, "Mercenary liaison");
break;
default:
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
break;
}
}
else
{
strcpy(ns2->spawn.lastName, ns->spawn.lastName);
}
memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7);
}
@@ -904,7 +924,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
}
ns->spawn.guildrank = 0xFF;
ns->spawn.size = size;
ns->spawn.size = size;
ns->spawn.bodytype = bodytype;
// The 'flymode' settings have the following effect:
// 0 - Mobs in water sink like a stone to the bottom
@@ -1229,7 +1249,7 @@ void Mob::ShowStats(Client* client)
}
else if (IsCorpse()) {
if (IsPlayerCorpse()) {
client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetDBID());
client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetCorpseDBID());
}
else {
client->Message(0, " NPCCorpse", GetID());
@@ -1350,147 +1370,150 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
uint16 BaseRace = GetBaseRace();
if (in_race == 0) {
this->race = BaseRace;
if (in_race == 0)
{
race = BaseRace;
if (in_gender == 0xFF)
this->gender = GetBaseGender();
else
this->gender = in_gender;
}
else {
this->race = in_race;
if (in_gender == 0xFF) {
uint8 tmp = Mob::GetDefaultGender(this->race, gender);
if (tmp == 2)
gender = 2;
else if (gender == 2 && GetBaseGender() == 2)
gender = tmp;
else if (gender == 2)
gender = GetBaseGender();
}
gender = GetBaseGender();
else
gender = in_gender;
}
if (in_texture == 0xFF) {
if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522)
this->texture = 0xFF;
else
this->texture = GetTexture();
}
else
this->texture = in_texture;
{
race = in_race;
if (in_gender == 0xFF)
gender = GetDefaultGender(race, gender);
else
gender = in_gender;
}
if (in_helmtexture == 0xFF) {
if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522)
this->helmtexture = 0xFF;
else if (in_texture != 0xFF)
this->helmtexture = in_texture;
if (in_texture == 0xFF)
{
if (IsPlayerRace(in_race))
texture = 0xFF;
else
this->helmtexture = GetHelmTexture();
texture = GetTexture();
}
else
this->helmtexture = in_helmtexture;
{
texture = in_texture;
}
if (in_helmtexture == 0xFF)
{
if (IsPlayerRace(in_race))
helmtexture = 0xFF;
else if (in_texture != 0xFF)
helmtexture = in_texture;
else
helmtexture = GetHelmTexture();
}
else
{
helmtexture = in_helmtexture;
}
if (in_haircolor == 0xFF)
this->haircolor = GetHairColor();
haircolor = GetHairColor();
else
this->haircolor = in_haircolor;
haircolor = in_haircolor;
if (in_beardcolor == 0xFF)
this->beardcolor = GetBeardColor();
beardcolor = GetBeardColor();
else
this->beardcolor = in_beardcolor;
beardcolor = in_beardcolor;
if (in_eyecolor1 == 0xFF)
this->eyecolor1 = GetEyeColor1();
eyecolor1 = GetEyeColor1();
else
this->eyecolor1 = in_eyecolor1;
eyecolor1 = in_eyecolor1;
if (in_eyecolor2 == 0xFF)
this->eyecolor2 = GetEyeColor2();
eyecolor2 = GetEyeColor2();
else
this->eyecolor2 = in_eyecolor2;
eyecolor2 = in_eyecolor2;
if (in_hairstyle == 0xFF)
this->hairstyle = GetHairStyle();
hairstyle = GetHairStyle();
else
this->hairstyle = in_hairstyle;
hairstyle = in_hairstyle;
if (in_luclinface == 0xFF)
this->luclinface = GetLuclinFace();
luclinface = GetLuclinFace();
else
this->luclinface = in_luclinface;
luclinface = in_luclinface;
if (in_beard == 0xFF)
this->beard = GetBeard();
beard = GetBeard();
else
this->beard = in_beard;
beard = in_beard;
this->aa_title = 0xFF;
aa_title = in_aa_title;
if (in_drakkin_heritage == 0xFFFFFFFF)
this->drakkin_heritage = GetDrakkinHeritage();
drakkin_heritage = GetDrakkinHeritage();
else
this->drakkin_heritage = in_drakkin_heritage;
drakkin_heritage = in_drakkin_heritage;
if (in_drakkin_tattoo == 0xFFFFFFFF)
this->drakkin_tattoo = GetDrakkinTattoo();
drakkin_tattoo = GetDrakkinTattoo();
else
this->drakkin_tattoo = in_drakkin_tattoo;
drakkin_tattoo = in_drakkin_tattoo;
if (in_drakkin_details == 0xFFFFFFFF)
this->drakkin_details = GetDrakkinDetails();
drakkin_details = GetDrakkinDetails();
else
this->drakkin_details = in_drakkin_details;
drakkin_details = in_drakkin_details;
if (in_size <= 0.0f)
this->size = GetSize();
size = GetSize();
else
this->size = in_size;
size = in_size;
// Forces the feature information to be pulled from the Player Profile
if (this->IsClient() && in_race == 0) {
this->race = CastToClient()->GetBaseRace();
this->gender = CastToClient()->GetBaseGender();
this->texture = 0xFF;
this->helmtexture = 0xFF;
this->haircolor = CastToClient()->GetBaseHairColor();
this->beardcolor = CastToClient()->GetBaseBeardColor();
this->eyecolor1 = CastToClient()->GetBaseEyeColor();
this->eyecolor2 = CastToClient()->GetBaseEyeColor();
this->hairstyle = CastToClient()->GetBaseHairStyle();
this->luclinface = CastToClient()->GetBaseFace();
this->beard = CastToClient()->GetBaseBeard();
this->aa_title = 0xFF;
this->drakkin_heritage = CastToClient()->GetBaseHeritage();
this->drakkin_tattoo = CastToClient()->GetBaseTattoo();
this->drakkin_details = CastToClient()->GetBaseDetails();
// Reset features to Base from the Player Profile
if (IsClient() && in_race == 0)
{
race = CastToClient()->GetBaseRace();
gender = CastToClient()->GetBaseGender();
texture = 0xFF;
helmtexture = 0xFF;
haircolor = CastToClient()->GetBaseHairColor();
beardcolor = CastToClient()->GetBaseBeardColor();
eyecolor1 = CastToClient()->GetBaseEyeColor();
eyecolor2 = CastToClient()->GetBaseEyeColor();
hairstyle = CastToClient()->GetBaseHairStyle();
luclinface = CastToClient()->GetBaseFace();
beard = CastToClient()->GetBaseBeard();
aa_title = 0xFF;
drakkin_heritage = CastToClient()->GetBaseHeritage();
drakkin_tattoo = CastToClient()->GetBaseTattoo();
drakkin_details = CastToClient()->GetBaseDetails();
switch(race){
case OGRE:
this->size = 9;
size = 9;
break;
case TROLL:
this->size = 8;
size = 8;
break;
case VAHSHIR:
case BARBARIAN:
this->size = 7;
size = 7;
break;
case HALF_ELF:
case WOOD_ELF:
case DARK_ELF:
case FROGLOK:
this->size = 5;
size = 5;
break;
case DWARF:
this->size = 4;
size = 4;
break;
case HALFLING:
case GNOME:
this->size = 3;
size = 3;
break;
default:
this->size = 6;
size = 6;
break;
}
}
@@ -1498,39 +1521,250 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct));
memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer));
Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer;
is->spawnid = this->GetID();
is->spawnid = GetID();
strcpy(is->charname, GetCleanName());
is->race = this->race;
is->gender = this->gender;
is->texture = this->texture;
is->helmtexture = this->helmtexture;
is->haircolor = this->haircolor;
is->beardcolor = this->beardcolor;
is->beard = this->beard;
is->eyecolor1 = this->eyecolor1;
is->eyecolor2 = this->eyecolor2;
is->hairstyle = this->hairstyle;
is->face = this->luclinface;
//is->aa_title = this->aa_title;
is->drakkin_heritage = this->drakkin_heritage;
is->drakkin_tattoo = this->drakkin_tattoo;
is->drakkin_details = this->drakkin_details;
is->size = this->size;
is->race = race;
is->gender = gender;
is->texture = texture;
is->helmtexture = helmtexture;
is->haircolor = haircolor;
is->beardcolor = beardcolor;
is->beard = beard;
is->eyecolor1 = eyecolor1;
is->eyecolor2 = eyecolor2;
is->hairstyle = hairstyle;
is->face = luclinface;
is->drakkin_heritage = drakkin_heritage;
is->drakkin_tattoo = drakkin_tattoo;
is->drakkin_details = drakkin_details;
is->size = size;
entity_list.QueueClients(this, outapp);
safe_delete(outapp);
mlog(CLIENT__SPELLS, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f",
this->race, this->gender, this->texture, this->helmtexture, this->haircolor, this->beardcolor, this->eyecolor1, this->eyecolor2, this->hairstyle, this->luclinface, this->drakkin_heritage, this->drakkin_tattoo, this->drakkin_details, this->size);
race, gender, texture, helmtexture, haircolor, beardcolor, eyecolor1, eyecolor2, hairstyle, luclinface, drakkin_heritage, drakkin_tattoo, drakkin_details, size);
}
bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
{
if (IsPlayerRace(GetRace()))
{
uint8 Gender = GetGender();
uint8 Texture = 0xFF;
uint8 HelmTexture = 0xFF;
uint8 HairColor = 0xFF;
uint8 BeardColor = 0xFF;
uint8 EyeColor1 = 0xFF;
uint8 EyeColor2 = 0xFF;
uint8 HairStyle = 0xFF;
uint8 LuclinFace = 0xFF;
uint8 Beard = 0xFF;
uint32 DrakkinHeritage = 0xFFFFFFFF;
uint32 DrakkinTattoo = 0xFFFFFFFF;
uint32 DrakkinDetails = 0xFFFFFFFF;
// Set some common feature settings
EyeColor1 = zone->random.Int(0, 9);
EyeColor2 = zone->random.Int(0, 9);
LuclinFace = zone->random.Int(0, 7);
// Adjust all settings based on the min and max for each feature of each race and gender
switch (GetRace())
{
case 1: // Human
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 2: // Barbarian
HairColor = zone->random.Int(0, 19);
LuclinFace = zone->random.Int(0, 87);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 3: // Erudite
if (Gender == 0) {
BeardColor = zone->random.Int(0, 19);
Beard = zone->random.Int(0, 5);
LuclinFace = zone->random.Int(0, 57);
}
if (Gender == 1) {
LuclinFace = zone->random.Int(0, 87);
}
break;
case 4: // WoodElf
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 5: // HighElf
HairColor = zone->random.Int(0, 14);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 6: // DarkElf
HairColor = zone->random.Int(13, 18);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 7: // HalfElf
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
LuclinFace = zone->random.Int(0, 37);
BeardColor = HairColor;
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 8: // Dwarf
HairColor = zone->random.Int(0, 19);
BeardColor = HairColor;
if (Gender == 0) {
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
LuclinFace = zone->random.Int(0, 17);
}
break;
case 9: // Troll
EyeColor1 = zone->random.Int(0, 10);
EyeColor2 = zone->random.Int(0, 10);
if (Gender == 1) {
HairStyle = zone->random.Int(0, 3);
HairColor = zone->random.Int(0, 23);
}
break;
case 10: // Ogre
if (Gender == 1) {
HairStyle = zone->random.Int(0, 3);
HairColor = zone->random.Int(0, 23);
}
break;
case 11: // Halfling
HairColor = zone->random.Int(0, 19);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 12: // Gnome
HairColor = zone->random.Int(0, 24);
if (Gender == 0) {
BeardColor = HairColor;
HairStyle = zone->random.Int(0, 3);
Beard = zone->random.Int(0, 5);
}
if (Gender == 1) {
HairStyle = zone->random.Int(0, 2);
}
break;
case 128: // Iksar
case 130: // VahShir
break;
case 330: // Froglok
LuclinFace = zone->random.Int(0, 9);
case 522: // Drakkin
HairColor = zone->random.Int(0, 3);
BeardColor = HairColor;
EyeColor1 = zone->random.Int(0, 11);
EyeColor2 = zone->random.Int(0, 11);
LuclinFace = zone->random.Int(0, 6);
DrakkinHeritage = zone->random.Int(0, 6);
DrakkinTattoo = zone->random.Int(0, 7);
DrakkinDetails = zone->random.Int(0, 7);
if (Gender == 0) {
Beard = zone->random.Int(0, 12);
HairStyle = zone->random.Int(0, 8);
}
if (Gender == 1) {
Beard = zone->random.Int(0, 3);
HairStyle = zone->random.Int(0, 7);
}
break;
default:
break;
}
if (set_variables)
{
haircolor = HairColor;
beardcolor = BeardColor;
eyecolor1 = EyeColor1;
eyecolor2 = EyeColor2;
hairstyle = HairStyle;
luclinface = LuclinFace;
beard = Beard;
drakkin_heritage = DrakkinHeritage;
drakkin_tattoo = DrakkinTattoo;
drakkin_details = DrakkinDetails;
}
if (send_illusion)
{
SendIllusionPacket(GetRace(), Gender, Texture, HelmTexture, HairColor, BeardColor,
EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage,
DrakkinTattoo, DrakkinDetails);
}
return true;
}
return false;
}
bool Mob::IsPlayerRace(uint16 in_race) {
if ((in_race >= HUMAN && in_race <= GNOME) || in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN)
{
return true;
}
return false;
}
uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) {
//std::cout << "Gender in: " << (int)in_gender << std::endl; // undefined cout [CODEBUG]
if ((in_race > 0 && in_race <= GNOME )
|| in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN
|| in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) {
if (Mob::IsPlayerRace(in_race) || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) {
if (in_gender >= 2) {
// Female default for PC Races
return 1;
// Male default for PC Races
return 0;
}
else
return in_gender;
@@ -2317,7 +2551,7 @@ uint32 Mob::RandomTimer(int min,int max) {
int r = 14000;
if(min != 0 && max != 0 && min < max)
{
r = MakeRandomInt(min, max);
r = zone->random.Int(min, max);
}
return r;
}
@@ -2427,6 +2661,9 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
return atoi(&item->IDFile[2]);
}
else if (inst->GetOrnamentationIcon() && inst->GetOrnamentationIDFile()) {
return inst->GetOrnamentationIDFile();
}
else {
if (strlen(item->IDFile) > 2)
return atoi(&item->IDFile[2]);
@@ -2707,7 +2944,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
if(IsClient())
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance))
if(twinproc_chance && zone->random.Roll(twinproc_chance))
twinproc = true;
if (IsBeneficialSpell(spell_id)) {
@@ -3024,7 +3261,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
if(IsValidSpell(trigger_spell_id) && GetTarget()){
SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff);
CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell);
CheckNumHitsRemaining(NUMHIT_MatchingSpells,-1, focus_spell);
}
}
}
@@ -3049,7 +3286,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
{
if (spells[spell_id].effectid[i] == SE_SpellTrigger)
{
if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i])
if(zone->random.Int(0, trig_chance) <= spells[spell_id].base[i])
{
// If we trigger an effect then its over.
if (IsValidSpell(spells[spell_id].base2[i])){
@@ -3069,7 +3306,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
// if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well.
else
{
if(MakeRandomInt(0, 100) <= spells[spell_id].base[effect])
if(zone->random.Int(0, 100) <= spells[spell_id].base[effect])
{
if (IsValidSpell(spells[spell_id].base2[effect])){
SpellFinished(spells[spell_id].base2[effect], target, 10, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff);
@@ -3174,7 +3411,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
if (focus > 0)
{
if(MakeRandomInt(0, 100) <= focus)
if(zone->random.Roll(focus))
{
Message(MT_Spells,"You twincast %s!",spells[spell_id].name);
SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff);
@@ -3193,7 +3430,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id);
if(focus > 0)
{
if(MakeRandomInt(0, 100) <= focus)
if(zone->random.Roll(focus))
{
SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff);
}
@@ -3361,7 +3598,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell);
CheckNumHitsRemaining(NUMHIT_MatchingSpells, -1, focus_spell);
}
}
@@ -3974,7 +4211,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
{
if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level)
{
if(MakeRandomInt(0,99) < spells[spell_id].base[i])
if(zone->random.Roll(spells[spell_id].base[i]))
SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
}
}
@@ -3989,17 +4226,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id)
for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) {
if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) {
if(MakeRandomInt(0, 99) < static_cast<int>(aabonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnKill[i + 1])))
SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){
if(MakeRandomInt(0, 99) < static_cast<int>(itembonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnKill[i + 1])))
SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) {
if(MakeRandomInt(0, 99) < static_cast<int>(spellbonuses.SpellOnKill[i + 1]))
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnKill[i + 1])))
SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff);
}
@@ -4016,19 +4253,19 @@ bool Mob::TrySpellOnDeath()
for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) {
if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(aabonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(aabonuses.SpellOnDeath[i + 1]))) {
SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff);
}
}
if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(itembonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(itembonuses.SpellOnDeath[i + 1]))) {
SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff);
}
}
if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) {
if(MakeRandomInt(0, 99) < static_cast<int>(spellbonuses.SpellOnDeath[i + 1])) {
if(zone->random.Roll(static_cast<int>(spellbonuses.SpellOnDeath[i + 1]))) {
SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff);
}
}
@@ -4191,55 +4428,12 @@ bool Mob::TryReflectSpell(uint32 spell_id)
int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance;
if(chance && MakeRandomInt(0, 99) < chance)
if(chance && zone->random.Roll(chance))
return true;
return false;
}
void Mob::SpellProjectileEffect()
{
bool time_disable = false;
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) {
if (projectile_increment[i] == 0){
continue;
}
Mob* target = entity_list.GetMobID(projectile_target_id[i]);
float dist = 0;
if (target)
dist = target->CalculateDistance(projectile_x[i], projectile_y[i], projectile_z[i]);
int increment_end = 0;
increment_end = static_cast<int>(dist / 10) - 1; //This pretty accurately determines end time for speed for 1.5 and timer of 250 ms
if (increment_end <= projectile_increment[i]){
if (target && IsValidSpell(projectile_spell_id[i]))
SpellOnTarget(projectile_spell_id[i], target, false, true, spells[projectile_spell_id[i]].ResistDiff, true);
projectile_spell_id[i] = 0;
projectile_target_id[i] = 0;
projectile_x[i] = 0, projectile_y[i] = 0, projectile_z[i] = 0;
projectile_increment[i] = 0;
time_disable = true;
}
else {
projectile_increment[i]++;
time_disable = false;
}
}
if (time_disable)
projectile_timer.Disable();
}
void Mob::DoGravityEffect()
{
Mob *caster = nullptr;
+24 -14
View File
@@ -18,7 +18,6 @@
#ifndef MOB_H
#define MOB_H
#include "../common/features.h"
#include "common.h"
#include "entity.h"
#include "hate_list.h"
@@ -26,14 +25,22 @@
#include "position.h"
#include <set>
#include <vector>
#include <string>
char* strn0cpy(char* dest, const char* source, uint32 size);
#define MAX_SPECIAL_ATTACK_PARAMS 8
class EGNode;
class MobFearState;
class Client;
class EQApplicationPacket;
class Group;
class ItemInst;
class NPC;
class Raid;
struct Item_Struct;
struct NewSpawn_Struct;
struct PlayerPositionUpdateServer_Struct;
class Mob : public Entity {
public:
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
@@ -228,8 +235,7 @@ public:
uint16 CastingSpellID() const { return casting_spell_id; }
bool DoCastingChecks();
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
void SpellProjectileEffect();
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id);
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
void ResourceTap(int32 damage, uint16 spell_id);
void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker);
bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id);
@@ -273,7 +279,7 @@ public:
int16 GetBuffSlotFromType(uint16 type);
uint16 GetSpellIDFromSlot(uint8 slot);
int CountDispellableBuffs();
void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN);
void CheckNumHitsRemaining(uint8 type, int32 buff_slot=-1, uint16 spell_id=SPELL_UNKNOWN);
bool HasNumhits() const { return has_numhits; }
inline void Numhits(bool val) { has_numhits = val; }
bool HasMGB() const { return has_MGB; }
@@ -490,6 +496,7 @@ public:
//Util
static uint32 RandomTimer(int min, int max);
static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF);
static bool IsPlayerRace(uint16 in_race);
uint16 GetSkillByItemType(int ItemType);
uint8 GetItemTypeBySkill(SkillUseTypes skill);
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
@@ -570,6 +577,7 @@ public:
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f);
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
virtual void Stun(int duration);
virtual void UnStun();
inline void Silence(bool newval) { silenced = newval; }
@@ -721,9 +729,14 @@ public:
int32 ReduceAllDamage(int32 damage);
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0);
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f);
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0);
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f);
bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed);
void ProjectileAttack();
inline bool HasProjectileAttack() const { return ActiveProjectileATK; }
inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; }
float GetRangeDistTargetSizeMod(Mob* other);
bool CanDoSpecialAttack(Mob *other);
bool Flurry(ExtraAttackOptions *opts);
bool Rampage(ExtraAttackOptions *opts);
@@ -839,7 +852,7 @@ public:
// HP Event
inline int GetNextHPEvent() const { return nexthpevent; }
void SetNextHPEvent( int hpevent );
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse);
void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0);
inline int& GetNextIncHPEvent() { return nextinchpevent; }
void SetNextIncHPEvent( int inchpevent );
@@ -1079,11 +1092,8 @@ protected:
uint8 bardsong_slot;
uint32 bardsong_target_id;
Timer projectile_timer;
uint32 projectile_spell_id[MAX_SPELL_PROJECTILE];
uint16 projectile_target_id[MAX_SPELL_PROJECTILE];
uint8 projectile_increment[MAX_SPELL_PROJECTILE];
float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE];
bool ActiveProjectileATK;
tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE];
xyz_location m_RewindLocation;
+31 -33
View File
@@ -57,7 +57,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
return false;
if (iChance < 100) {
if (MakeRandomInt(0, 100) >= iChance)
if (zone->random.Int(0, 100) >= iChance)
return false;
}
@@ -94,7 +94,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range
)
&& (mana_cost <= GetMana() || GetMana() == GetMaxMana())
&& (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
&& (AIspells[i].time_cancast + (zone->random.Int(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time.
) {
#if MobAI_DEBUG_Spells >= 21
@@ -126,7 +126,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Root: {
Mob *rootee = GetHateRandom();
if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50
if (rootee && !rootee->IsRooted() && zone->random.Roll(50)
&& rootee->DontRootMeBefore() < Timer::GetCurrentTime()
&& rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -165,7 +165,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_InCombatBuff: {
if(MakeRandomInt(0, 99) < 50)
if(zone->random.Roll(50))
{
AIDoSpellCast(i, tar, mana_cost);
return true;
@@ -184,7 +184,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Slow:
case SpellType_Debuff: {
Mob * debuffee = GetHateRandom();
if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) &&
if (debuffee && manaR >= 10 && zone->random.Roll(70) &&
debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) {
if (!checked_los) {
if (!CheckLosFN(debuffee))
@@ -198,7 +198,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Nuke: {
if (
manaR >= 10 && MakeRandomInt(0, 99) < 70
manaR >= 10 && zone->random.Roll(70)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@@ -212,7 +212,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Dispel: {
if(MakeRandomInt(0, 99) < 15)
if(zone->random.Roll(15))
{
if(!checked_los) {
if(!CheckLosFN(tar))
@@ -228,7 +228,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
break;
}
case SpellType_Mez: {
if(MakeRandomInt(0, 99) < 20)
if(zone->random.Roll(20))
{
Mob * mezTar = nullptr;
mezTar = entity_list.GetTargetForMez(this);
@@ -244,7 +244,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Charm:
{
if(!IsPet() && MakeRandomInt(0, 99) < 20)
if(!IsPet() && zone->random.Roll(20))
{
Mob * chrmTar = GetHateRandom();
if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0)
@@ -258,7 +258,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Pet: {
//keep mobs from recasting pets when they have them.
if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) {
if (!IsPet() && !GetPetID() && zone->random.Roll(25)) {
AIDoSpellCast(i, tar, mana_cost);
return true;
}
@@ -266,7 +266,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_Lifetap: {
if (GetHPRatio() <= 95
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
if(!checked_los) {
@@ -282,7 +282,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
case SpellType_Snare: {
if (
!tar->IsRooted()
&& MakeRandomInt(0, 99) < 50
&& zone->random.Roll(50)
&& tar->DontSnareMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -300,7 +300,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) {
}
case SpellType_DOT: {
if (
MakeRandomInt(0, 99) < 60
zone->random.Roll(60)
&& tar->DontDotMeBefore() < Timer::GetCurrentTime()
&& tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0
) {
@@ -369,7 +369,7 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
return false;
if (iChance < 100) {
uint8 tmp = MakeRandomInt(0, 99);
uint8 tmp = zone->random.Int(0, 99);
if (tmp >= iChance)
return false;
}
@@ -594,7 +594,6 @@ void Mob::AI_ShutDown() {
tic_timer.Disable();
mana_timer.Disable();
spellend_timer.Disable();
projectile_timer.Disable();
rewind_timer.Disable();
bindwound_timer.Disable();
stunned_timer.Disable();
@@ -685,7 +684,7 @@ void Client::AI_SpellCast()
}
else
{
uint32 idx = MakeRandomInt(0, (valid_spells.size()-1));
uint32 idx = zone->random.Int(0, (valid_spells.size()-1));
spell_to_cast = valid_spells[idx];
slot_to_use = slots[idx];
}
@@ -873,7 +872,7 @@ void Client::AI_Process()
if (flurrychance)
{
if(MakeRandomInt(0, 100) < flurrychance)
if(zone->random.Roll(flurrychance))
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), MainPrimary, false);
@@ -890,7 +889,7 @@ void Client::AI_Process()
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus)
if(zone->random.Roll(ExtraAttackChanceBonus))
{
Attack(GetTarget(), MainPrimary, false);
}
@@ -929,7 +928,7 @@ void Client::AI_Process()
int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance;
DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(GetTarget(), MainSecondary);
if(CheckDoubleAttack())
@@ -1190,7 +1189,7 @@ void Mob::AI_Process() {
//we use this random value in three comparisons with different
//thresholds, and if its truely random, then this should work
//out reasonably and will save us compute resources.
int32 RandRoll = MakeRandomInt(0, 99);
int32 RandRoll = zone->random.Int(0, 99);
if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE)
|| GetSpecialAbility(SPECATK_QUAD))
//check double attack, this is NOT the same rules that clients use...
@@ -1214,7 +1213,7 @@ void Mob::AI_Process() {
int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0);
flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance);
if (MakeRandomInt(0, 99) < flurry_chance) {
if (zone->random.Roll(flurry_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2);
if (cur > 0)
@@ -1256,7 +1255,7 @@ void Mob::AI_Process() {
int16 flurry_chance = owner->aabonuses.PetFlurry +
owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry;
if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance))
if (flurry_chance && zone->random.Roll(flurry_chance))
Flurry(nullptr);
}
}
@@ -1265,7 +1264,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2);
if(cur > 0) {
@@ -1304,7 +1303,7 @@ void Mob::AI_Process() {
{
int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0);
rampage_chance = rampage_chance > 0 ? rampage_chance : 20;
if(MakeRandomInt(0, 99) < rampage_chance) {
if(zone->random.Roll(rampage_chance)) {
ExtraAttackOptions opts;
int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2);
if(cur > 0) {
@@ -1348,13 +1347,12 @@ void Mob::AI_Process() {
//can only dual wield without a weapon if your a monk
if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) {
float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f;
if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability)
if(zone->random.Roll(DualWieldProbability))
{
Attack(target, MainSecondary);
if (CanThisClassDoubleAttack())
{
int32 RandRoll = MakeRandomInt(0, 99);
if (RandRoll < (GetLevel() + 20))
if (zone->random.Roll(GetLevel() + 20))
{
Attack(target, MainSecondary);
}
@@ -1619,12 +1617,12 @@ void NPC::AI_DoMovement() {
)
{
float movedist = roambox_distance*roambox_distance;
float movex = MakeRandomFloat(0, movedist);
float movex = zone->random.Real(0, movedist);
float movey = movedist - movex;
movex = sqrtf(movex);
movey = sqrtf(movey);
movex *= MakeRandomInt(0, 1) ? 1 : -1;
movey *= MakeRandomInt(0, 1) ? 1 : -1;
movex *= zone->random.Int(0, 1) ? 1 : -1;
movey *= zone->random.Int(0, 1) ? 1 : -1;
roambox_movingto_x = GetX() + movex;
roambox_movingto_y = GetY() + movey;
//Try to calculate new coord using distance.
@@ -1635,9 +1633,9 @@ void NPC::AI_DoMovement() {
//New coord is still invalid, ignore distance and just pick a new random coord.
//If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc.
if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x)
roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1);
roambox_movingto_x = zone->random.Real(roambox_min_x+1,roambox_max_x-1);
if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y)
roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1);
roambox_movingto_y = zone->random.Real(roambox_min_y+1,roambox_max_y-1);
}
mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
@@ -1879,7 +1877,7 @@ void Mob::AI_Event_NoLongerEngaged() {
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
pLastFightingDelayMoving += minLastFightingDelayMoving;
else
pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving);
pLastFightingDelayMoving += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
// So mobs don't keep running as a ghost until AIwalking_timer fires
// if they were moving prior to losing all hate
if(IsMoving()){
+10 -17
View File
@@ -1,22 +1,15 @@
#include "../common/debug.h"
#include "../common/timer.h"
#include <cmath>
#include <stdlib.h>
#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 "entity.h"
#include "mob.h"
#include "npc.h"
#include "worldserver.h"
#include "quest_parser_collection.h"
#include "event_codes.h"
#include "embparser.h"
#include <string>
#include <iostream>
#include "zone.h"
class ItemInst;
class Spawn2;
struct Consider_Struct;
struct DBTradeskillRecipe_Struct;
struct Item_Struct;
extern EntityList entity_list;
extern Zone* zone;
+1 -2
View File
@@ -97,7 +97,7 @@ extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
QueryServ *QServ = 0;
QueryServ *QServ = 0;
TaskManager *taskmanager = 0;
QuestParserCollection *parse = 0;
@@ -642,4 +642,3 @@ void UpdateWindowTitle(char* iNewTitle) {
SetConsoleTitle(tmp);
#endif
}
-3
View File
@@ -26,9 +26,6 @@
#include <netdb.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include "../common/types.h"
#include "../common/timer.h"
void CatchSignal(int);
+38 -37
View File
@@ -15,15 +15,34 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include <iostream>
#include <string>
#include <cctype>
#include <math.h>
#include "../common/moremath.h"
#include <stdio.h>
#include "../common/packet_dump_file.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "../common/seperator.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/clientversions.h"
#include "../common/features.h"
#include "../common/item.h"
#include "../common/item_struct.h"
#include "../common/linked_list.h"
#include "../common/servertalk.h"
#include "aa.h"
#include "client.h"
#include "entity.h"
#include "npc.h"
#include "string_ids.h"
#include "spawn2.h"
#include "zone.h"
#include <cctype>
#include <stdio.h>
#include <string>
#ifdef _WINDOWS
#define snprintf _snprintf
#define strncasecmp _strnicmp
@@ -33,27 +52,10 @@
#include <pthread.h>
#endif
#include "npc.h"
#include "map.h"
#include "entity.h"
#include "masterentity.h"
#include "../common/spdat.h"
#include "../common/bodytypes.h"
#include "spawngroup.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "string_ids.h"
//#define SPELLQUEUE //Use only if you want to be spammed by spell testing
extern Zone* zone;
extern volatile bool ZoneLoaded;
extern EntityList entity_list;
#include "quest_parser_collection.h"
NPC::NPC(const NPCType* d, Spawn2* in_respawn, const xyz_heading& position, int iflymode, bool IsCorpse)
: Mob(d->name,
d->lastname,
@@ -283,7 +285,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const xyz_heading& position, int
if(trap_list.size() > 0)
{
std::list<LDoNTrapTemplate*>::iterator trap_list_iter = trap_list.begin();
std::advance(trap_list_iter, MakeRandomInt(0, trap_list.size() - 1));
std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1));
LDoNTrapTemplate* tt = (*trap_list_iter);
if(tt)
{
@@ -536,10 +538,10 @@ void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_
}
void NPC::AddCash() {
copper = MakeRandomInt(1, 100);
silver = MakeRandomInt(1, 50);
gold = MakeRandomInt(1, 10);
platinum = MakeRandomInt(1, 5);
copper = zone->random.Int(1, 100);
silver = zone->random.Int(1, 50);
gold = zone->random.Int(1, 10);
platinum = zone->random.Int(1, 5);
}
void NPC::RemoveCash() {
@@ -656,8 +658,7 @@ bool NPC::Process()
viral_timer_counter = 0;
}
if(projectile_timer.Check())
SpellProjectileEffect();
ProjectileAttack();
if(spellbonuses.GravityEffect == 1) {
if(gravity_timer.Check())
@@ -1359,7 +1360,7 @@ void NPC::PickPocket(Client* thief) {
return;
}
if(MakeRandomInt(0, 100) > 95){
if(zone->random.Roll(5)) {
AddToHateList(thief, 50);
Say("Stop thief!");
thief->Message(13, "You are noticed trying to steal!");
@@ -1388,7 +1389,7 @@ void NPC::PickPocket(Client* thief) {
memset(charges,0,50);
//Determine wheter to steal money or an item.
bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0);
bool steal_item = (MakeRandomInt(0, 99) < 50 || no_coin);
bool steal_item = (zone->random.Roll(50) || no_coin);
if (steal_item)
{
ItemList::iterator cur,end;
@@ -1418,7 +1419,7 @@ void NPC::PickPocket(Client* thief) {
}
if (x > 0)
{
int random = MakeRandomInt(0, x-1);
int random = zone->random.Int(0, x-1);
inst = database.CreateItem(steal_items[random], charges[random]);
if (inst)
{
@@ -1453,7 +1454,7 @@ void NPC::PickPocket(Client* thief) {
}
if (!steal_item) //Steal money
{
uint32 amt = MakeRandomInt(1, (steal_skill/25)+1);
uint32 amt = zone->random.Int(1, (steal_skill/25)+1);
int steal_type = 0;
if (!money[0])
{
@@ -1468,7 +1469,7 @@ void NPC::PickPocket(Client* thief) {
}
}
if (MakeRandomInt(0, 100) <= stealchance)
if (zone->random.Roll(stealchance))
{
switch (steal_type)
{
@@ -1949,7 +1950,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
void NPC::LevelScale() {
uint8 random_level = (MakeRandomInt(level, maxlevel));
uint8 random_level = (zone->random.Int(level, maxlevel));
float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f));
+2446
View File
File diff suppressed because it is too large Load Diff
+16 -14
View File
@@ -18,20 +18,17 @@
#ifndef NPC_H
#define NPC_H
class NPC;
#include "zonedb.h"
#include "mob.h"
//#include "spawn.h"
#include <list>
#include <deque>
#include "spawn2.h"
#include "../common/loottable.h"
#include "zonedump.h"
#include "qglobals.h"
#include "../common/rulesys.h"
#include "mob.h"
#include "qglobals.h"
#include "zonedb.h"
#include "zonedump.h"
#include <deque>
#include <list>
#ifdef _WINDOWS
#define M_PI 3.141592
#endif
@@ -88,8 +85,12 @@ struct AISpellsVar_Struct {
uint8 idle_beneficial_chance;
};
class AA_SwarmPetInfo;
class Client;
class Group;
class Raid;
class Spawn2;
struct Item_Struct;
class NPC : public Mob
{
@@ -353,8 +354,9 @@ public:
const bool GetCombatEvent() const { return combat_event; }
void SetCombatEvent(bool b) { combat_event = b; }
//The corpse we make can only be looted by people who got credit for the kill
/* Only allows players that killed corpse to loot */
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
+2 -2
View File
@@ -441,8 +441,8 @@ void Object::RandomSpawn(bool send_packet) {
if(!m_ground_spawn)
return;
m_data.x = MakeRandomFloat(m_min_x, m_max_x);
m_data.y = MakeRandomFloat(m_min_y, m_max_y);
m_data.x = zone->random.Real(m_min_x, m_max_x);
m_data.y = zone->random.Real(m_min_y, m_max_y);
respawn_timer.Disable();
if(send_packet) {
+1 -1
View File
@@ -1346,7 +1346,7 @@ PathNode* PathManager::FindPathNodeByCoordinates(float x, float y, float z)
int PathManager::GetRandomPathNode()
{
return MakeRandomInt(0, Head.PathNodeCount - 1);
return zone->random.Int(0, Head.PathNodeCount - 1);
}
+4 -4
View File
@@ -208,7 +208,7 @@ XS(XS_Corpse_GetDBID)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetDBID();
RETVAL = THIS->GetCorpseDBID();
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
@@ -662,7 +662,7 @@ XS(XS_Corpse_CompleteRezz)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->CompleteRezz();
THIS->CompleteResurrection();
}
XSRETURN_EMPTY;
}
@@ -687,7 +687,7 @@ XS(XS_Corpse_CanMobLoot)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->CanMobLoot(charid);
RETVAL = THIS->CanPlayerLoot(charid);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
@@ -723,7 +723,7 @@ XS(XS_Corpse_AllowMobLoot)
if(them == nullptr)
Perl_croak(aTHX_ "them is nullptr, avoiding crash.");
THIS->AllowMobLoot(them, slot);
THIS->AllowPlayerLoot(them, slot);
}
XSRETURN_EMPTY;
}
+3 -12
View File
@@ -16,10 +16,6 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#ifdef _WINDOWS
#include <process.h>
@@ -32,16 +28,12 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
#include "../common/string_util.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "../common/packet_dump_file.h"
#include "../common/emu_opcodes.h"
#include "../common/eq_packet_structs.h"
#include "../common/servertalk.h"
#include "../common/string_util.h"
#include "entity.h"
#include "masterentity.h"
#include "petitions.h"
#include "worldserver.h"
@@ -49,7 +41,6 @@ PetitionList petition_list;
extern WorldServer worldserver;
void Petition::SendPetitionToPlayer(Client* clientto) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetitionCheckout,sizeof(Petition_Struct));
Petition_Struct* pet = (Petition_Struct*) outapp->pBuffer;
+6 -4
View File
@@ -19,11 +19,13 @@
#define PETITIONS_H
#include "../common/linked_list.h"
#include "../common/types.h"
#include "zonedb.h"
#include "client.h"
#include "../common/mutex.h"
#include "../common/misc_functions.h"
#include "../common/mutex.h"
#include "../common/types.h"
#include "client.h"
#include "zonedb.h"
class Client;
class Petition
{
+12 -16
View File
@@ -15,30 +15,26 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/misc_functions.h"
#include "../common/spdat.h"
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/moremath.h"
#include "../common/item.h"
#include "zonedb.h"
#include "worldserver.h"
#include "../common/skills.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/string_util.h"
#include "../common/types.h"
#include "entity.h"
#include "client.h"
#include "mob.h"
#include "pets.h"
#include <math.h>
#include <assert.h>
#include "worldserver.h"
#include "zonedb.h"
#ifndef WIN32
#include <stdlib.h>
#include "../common/unix.h"
#endif
#include "string_ids.h"
///////////////////////////////////////////////////////////////////////////////
// pet related functions
const char *GetRandPetName()
{
@@ -113,7 +109,7 @@ const char *GetRandPetName()
"Zibann","Zibarer","Zibartik","Zibekn","Zibn","Zibobn","Zobaner","Zobann",
"Zobarn","Zober","Zobn","Zonanab","Zonaner","Zonann","Zonantik","Zonarer",
"Zonartik","Zonobn","Zonobtik","Zontik","Ztik" };
int r = MakeRandomInt(0, (sizeof(petnames)/sizeof(const char *))-1);
int r = zone->random.Int(0, (sizeof(petnames)/sizeof(const char *))-1);
printf("Pet being created: %s\n",petnames[r]); // DO NOT COMMENT THIS OUT!
return petnames[r];
}
+16 -57
View File
@@ -16,66 +16,28 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Assuming you want to add a new perl quest function named joe
that takes 1 integer argument....
1. Add the prototype to the quest manager:
questmgr.h: add (~line 50)
void joe(int arg);
2. Define the actual function in questmgr.cpp:
void QuestManager::joe(int arg) {
//... do something
}
3. Copy one of the XS routines in perlparser.cpp, preferably
one with the same number of arguments as your routine. Rename
as needed.
Finally, add your routine to the list at the bottom of perlparser.cpp
4.
If you want it to work in old mode perl and .qst, edit parser.cpp
Parser::ExCommands (~line 777)
else if (!strcmp(command,"joe")) {
quest_manager.joe(atoi(arglist[0]));
}
And then at then end of embparser.cpp, add:
"sub joe{push(@cmd_queue,{func=>'joe',args=>join(',',@_)});}"
*/
#include "../common/debug.h"
#include "entity.h"
#include "masterentity.h"
#include <limits.h>
#include <sstream>
#include <iostream>
#include <list>
#include "worldserver.h"
#include "net.h"
#include "../common/skills.h"
#include "../common/classes.h"
#include "../common/races.h"
#include "zonedb.h"
#include "../common/debug.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/packet_functions.h"
#include "../common/string_util.h"
#include "spawn2.h"
#include "zone.h"
#include "entity.h"
#include "event_codes.h"
#include "guild_mgr.h"
#include "../common/rulesys.h"
#include "net.h"
#include "qglobals.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
#include "questmgr.h"
#include "quest_parser_collection.h"
#include "spawn2.h"
#include "worldserver.h"
#include "zone.h"
#include "zonedb.h"
#include <iostream>
#include <limits.h>
#include <list>
#ifdef BOTS
#include "bot.h"
#endif
@@ -85,9 +47,6 @@ extern Zone* zone;
extern WorldServer worldserver;
extern EntityList entity_list;
#include "questmgr.h"
//declare our global instance
QuestManager quest_manager;
#define QuestManagerCurrentQuestVars() \
@@ -1781,7 +1740,7 @@ bool QuestManager::buryplayercorpse(uint32 char_id)
if(corpse)
{
corpse->Save();
corpse->DepopCorpse();
corpse->DepopPlayerCorpse();
}
else
{
+3 -1
View File
@@ -25,8 +25,10 @@
#include <list>
#include <stack>
class NPC;
class Client;
class ItemInst;
class Mob;
class NPC;
class QuestManager {
struct running_quest {
+2 -2
View File
@@ -109,7 +109,7 @@ uint32 Spawn2::resetTimer()
if (variance_ != 0) {
int var_over_2 = (variance_ * 1000) / 2;
rspawn = MakeRandomInt(rspawn - var_over_2, rspawn + var_over_2);
rspawn = zone->random.Int(rspawn - var_over_2, rspawn + var_over_2);
//put a lower bound on it, not a lot of difference below 100, so set that as the bound.
if(rspawn < 100)
@@ -126,7 +126,7 @@ uint32 Spawn2::despawnTimer(uint32 despawn_timer)
if (variance_ != 0) {
int var_over_2 = (variance_ * 1000) / 2;
dspawn = MakeRandomInt(dspawn - var_over_2, dspawn + var_over_2);
dspawn = zone->random.Int(dspawn - var_over_2, dspawn + var_over_2);
//put a lower bound on it, not a lot of difference below 100, so set that as the bound.
if(dspawn < 100)
+3 -1
View File
@@ -25,8 +25,10 @@
#include "zonedb.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "zone.h"
extern EntityList entity_list;
extern Zone* zone;
SpawnEntry::SpawnEntry( uint32 in_NPCType, int in_chance, uint8 in_npc_spawn_limit ) {
NPCType = in_NPCType;
@@ -77,7 +79,7 @@ uint32 SpawnGroup::GetNPCType() {
int32 roll = 0;
roll = MakeRandomInt(0, totalchance-1);
roll = zone->random.Int(0, totalchance-1);
cur = possible.begin();
end = possible.end();
+508 -232
View File
File diff suppressed because it is too large Load Diff
+100 -102
View File
@@ -15,26 +15,24 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/spdat.h"
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/moremath.h"
#include "../common/item.h"
#include "worldserver.h"
#include "../common/skills.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/item.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include <math.h>
#include <assert.h>
#ifndef WIN32
#include <stdlib.h>
#include "../common/unix.h"
#endif
#include "string_ids.h"
#include "quest_parser_collection.h"
extern Zone* zone;
extern volatile bool ZoneLoaded;
@@ -457,7 +455,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if(IsClient())
{
if(MakeRandomInt(0, 99) < RuleI(Spells, SuccorFailChance)) { //2% Fail chance by default
if(zone->random.Roll(RuleI(Spells, SuccorFailChance))) { //2% Fail chance by default
if(IsClient()) {
CastToClient()->Message_StringID(MT_SpellFailure,SUCCOR_FAIL);
@@ -712,9 +710,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (IsClient())
stun_resist += aabonuses.StunResist;
if (stun_resist <= 0 || MakeRandomInt(0,99) >= stun_resist) {
if (stun_resist <= 0 || zone->random.Int(0,99) >= stun_resist) {
mlog(COMBAT__HITS, "Stunned. We had %d percent resist chance.", stun_resist);
if (caster->IsClient())
effect_value += effect_value*caster->CastToClient()->GetFocusEffect(focusFcStunTimeMod, spell_id)/100;
@@ -1035,8 +1033,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
#endif
if(!spellbonuses.AntiGate){
if(MakeRandomInt(0, 99) < effect_value)
Gate();
if(zone->random.Roll(effect_value))
Gate();
else
caster->Message_StringID(MT_SpellFailure,GATE_FAIL);
}
@@ -1477,16 +1475,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
#endif
int wipechance = spells[spell_id].base[i];
int bonus = 0;
if (caster){
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
caster->itembonuses.IncreaseChanceMemwipe +
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
caster->itembonuses.IncreaseChanceMemwipe +
caster->aabonuses.IncreaseChanceMemwipe;
}
wipechance += wipechance*bonus/100;
if(MakeRandomInt(0, 99) < wipechance)
if(zone->random.Roll(wipechance))
{
if(IsAIControlled())
{
@@ -1599,7 +1597,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if(IsClient()) {
if (MakeRandomInt(0, 99) > spells[spell_id].base[i]) {
if (zone->random.Int(0, 99) > spells[spell_id].base[i]) {
CastToClient()->SetFeigned(false);
entity_list.MessageClose_StringID(this, false, 200, 10, STRING_FEIGNFAILED, GetName());
}
@@ -1665,7 +1663,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Model Size: %d%%", effect_value);
#endif
ChangeSize(GetSize() * (static_cast<float>(effect_value) / 100.0f));
// Only allow 2 size changes from Base Size
float modifyAmount = (static_cast<float>(effect_value) / 100.0f);
float maxModAmount = GetBaseSize() * modifyAmount * modifyAmount;
if ((GetSize() <= GetBaseSize() && GetSize() > maxModAmount) ||
(GetSize() >= GetBaseSize() && GetSize() < maxModAmount) ||
(GetSize() <= GetBaseSize() && maxModAmount > 1.0f) ||
(GetSize() >= GetBaseSize() && maxModAmount < 1.0f))
{
ChangeSize(GetSize() * modifyAmount);
}
break;
}
@@ -2180,7 +2187,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
#ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Fading Memories");
#endif
if(MakeRandomInt(0, 99) < spells[spell_id].base[i] ) {
if(zone->random.Roll(spells[spell_id].base[i])) {
if(caster && caster->IsClient())
caster->CastToClient()->Escape();
@@ -2704,11 +2711,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}
}else{
int32 newhate = GetHateAmount(caster) + effect_value;
if (newhate < 1)
if (newhate < 1)
SetHate(caster,1);
else
else
SetHate(caster,newhate);
}
}
}
break;
}
@@ -2717,9 +2724,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if (buffslot >= 0)
break;
if(!spells[spell_id].uninterruptable && IsCasting() && MakeRandomInt(0, 100) <= spells[spell_id].base[i])
if(!spells[spell_id].uninterruptable && IsCasting() && zone->random.Roll(spells[spell_id].base[i]))
InterruptSpell();
break;
}
@@ -2735,17 +2742,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
Message(10, "The power of your next illusion spell will flow to your grouped target in your place.");
break;
}
case SE_ApplyEffect: {
if (caster && IsValidSpell(spells[spell_id].base2[i])){
if(MakeRandomInt(0, 100) <= spells[spell_id].base[i])
if(zone->random.Roll(spells[spell_id].base[i]))
caster->SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
}
break;
}
case SE_SpellTrigger: {
if (!SE_SpellTrigger_HasCast) {
@@ -3202,7 +3208,7 @@ snare has both of them negative, yet their range should work the same:
break;
}
case 123: // added 2/6/04
result = MakeRandomInt(ubase, abs(max));
result = zone->random.Int(ubase, abs(max));
break;
case 124: // check sign
@@ -3566,16 +3572,16 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
int wipechance = spells[spell_id].base[i];
int bonus = 0;
if (caster){
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
caster->itembonuses.IncreaseChanceMemwipe +
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
caster->itembonuses.IncreaseChanceMemwipe +
caster->aabonuses.IncreaseChanceMemwipe;
}
wipechance += wipechance*bonus/100;
if(MakeRandomInt(0, 99) < wipechance)
if(zone->random.Roll(wipechance))
{
if(IsAIControlled())
{
@@ -3595,16 +3601,14 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
}
case SE_Root: {
/* Root formula derived from extensive personal live parses - Kayen
ROOT has a 70% chance to do a resist check to break.
*/
if (MakeRandomInt(0, 99) < RuleI(Spells, RootBreakCheckChance)){
if (zone->random.Roll(RuleI(Spells, RootBreakCheckChance))) {
float resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster, 0,0,0,0,true);
if(resist_check == 100)
if(resist_check == 100)
break;
else
if(!TryFadeEffect(slot))
@@ -3616,11 +3620,10 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
case SE_Fear:
{
if (MakeRandomInt(0, 99) < RuleI(Spells, FearBreakCheckChance)){
if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) {
float resist_check = ResistSpell(spells[spell_id].resisttype, spell_id, caster);
if(resist_check == 100)
if(resist_check == 100)
break;
else
if(!TryFadeEffect(slot))
@@ -3657,7 +3660,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
break_chance -= (2 * (((double)GetSkill(SkillDivination) + ((double)GetLevel() * 3.0)) / 650.0));
}
if(MakeRandomFloat(0.0, 100.0) < break_chance)
if(zone->random.Real(0.0, 100.0) < break_chance)
{
BuffModifyDurationBySpellID(spell_id, 3);
}
@@ -3677,7 +3680,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
{
if(IsCasting())
{
if(MakeRandomInt(0, 100) <= spells[spell_id].base[i])
if(zone->random.Roll(spells[spell_id].base[i]))
{
InterruptSpell();
}
@@ -4575,11 +4578,9 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
case SE_TriggerOnCast:
if(type == focusTriggerOnCast){
if(MakeRandomInt(0, 100) <= base1){
if(zone->random.Roll(base1)) {
value = base2;
}
else{
} else {
value = 0;
LimitFailure = true;
}
@@ -4593,7 +4594,7 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
case SE_BlockNextSpellFocus:
if(type == focusBlockNextSpell){
if(MakeRandomInt(1, 100) <= base1)
if(zone->random.Roll(base1))
value = 1;
}
break;
@@ -4948,7 +4949,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -4967,7 +4968,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -4986,7 +4987,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
value = focus_spell.base[i];
}
else {
value = MakeRandomInt(focus_spell.base[i], focus_spell.base2[i]);
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
}
break;
@@ -5055,7 +5056,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_TriggerOnCast:
if(type == focusTriggerOnCast){
if(MakeRandomInt(1, 100) <= focus_spell.base[i])
if(zone->random.Roll(focus_spell.base[i]))
value = focus_spell.base2[i];
else
value = 0;
@@ -5064,7 +5065,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
case SE_BlockNextSpellFocus:
if(type == focusBlockNextSpell){
if(MakeRandomInt(1, 100) <= focus_spell.base[i])
if(zone->random.Roll(focus_spell.base[i]))
value = 1;
}
break;
@@ -5212,12 +5213,9 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
if (TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect)) {
proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id);
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItem->ProcRate);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
}
@@ -5233,14 +5231,10 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
{
const Item_Struct* TempItemAug = aug->GetItem();
if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) {
proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id);
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, spells[TempItemAug->Focus.Effect].base[0], TempItemAug->ProcRate);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
}
@@ -5268,8 +5262,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]);
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
}
@@ -5295,10 +5288,8 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
proc_spellid = CalcAAFocus(type, aa_AA, spell_id);
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1));
if(MakeRandomFloat(0, 1) <= ProcChance)
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
}
@@ -5306,7 +5297,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
if (SympatheticProcList.size() > 0)
{
uint8 random = MakeRandomInt(0, SympatheticProcList.size()-1);
uint8 random = zone->random.Int(0, SympatheticProcList.size()-1);
int FinalSympatheticProc = SympatheticProcList[random];
SympatheticProcList.clear();
return FinalSympatheticProc;
@@ -5549,7 +5540,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
return realTotal + realTotal2 + realTotal3;
}
void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
{
/*
Field 175 = numhits type
@@ -5586,8 +5577,8 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
}
}
}
} else if (type == 7) {
if (buff_slot > 0) {
} else if (type == NUMHIT_MatchingSpells) {
if (buff_slot >= 0) {
if (--buffs[buff_slot].numhits == 0) {
CastOnNumHitFade(buffs[buff_slot].spellid);
if (!TryFadeEffect(buff_slot))
@@ -5665,7 +5656,7 @@ bool Mob::TryDivineSave()
*/
int32 SuccessChance = aabonuses.DivineSaveChance[0] + itembonuses.DivineSaveChance[0] + spellbonuses.DivineSaveChance[0];
if (SuccessChance && MakeRandomInt(0, 100) <= SuccessChance)
if (SuccessChance && zone->random.Roll(SuccessChance))
{
SetHP(1);
@@ -5724,7 +5715,7 @@ bool Mob::TryDeathSave() {
if (SuccessChance > 95)
SuccessChance = 95;
if(SuccessChance >= MakeRandomInt(0, 100)) {
if(zone->random.Roll(SuccessChance)) {
if(spellbonuses.DeathSave[0] == 2)
HealAmt = RuleI(Spells, DivineInterventionHeal); //8000HP is how much LIVE Divine Intervention max heals
@@ -5755,7 +5746,7 @@ bool Mob::TryDeathSave() {
if (SuccessChance > 95)
SuccessChance = 95;
if(SuccessChance >= MakeRandomInt(0, 100)) {
if(zone->random.Roll(SuccessChance)) {
if(spellbonuses.DeathSave[0] == 2)
HealAmt = RuleI(Spells, DivineInterventionHeal);
@@ -6057,7 +6048,7 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){
else if (dispel_chance < 10)
dispel_chance = 10;
if (MakeRandomInt(0,99) < dispel_chance)
if (zone->random.Roll(dispel_chance))
return true;
else
return false;
@@ -6393,17 +6384,16 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama
return false;
}
bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){
/*For mage 'Bolt' line and other various spells.
-This is mostly accurate for how the modern clients handle this effect.
-It was changed at some point to use an actual projectile as done here (opposed to a particle effect in classic)
-The projectile graphic appears to be that of 'Ball of Sunlight' ID 80648 and will be visible to anyone in SoF+
-There is no LOS check to prevent a bolt from being cast. If you don't have LOS your bolt simply goes into whatever barrier
and you lose your mana. If there is LOS the bolt will lock onto your target and the damage is applied when it hits the target.
-If your target moves the bolt moves with it in any direction or angle (consistent with other projectiles).
-The way this is written once a bolt is cast a timer checks the distance from the initial cast to the target repeatedly
and calculates at what predicted time the bolt should hit that target in client_process (therefore accounting for any target movement).
-The way this is written once a bolt is cast a the distance from the initial cast to the target repeatedly
check and if target is moving recalculates at what predicted time the bolt should hit that target in client_process
When bolt hits its predicted point the damage is then done to target.
Note: Projectile speed of 1 takes 3 seconds to go 100 distance units. Calculations are based on this constant.
Live Bolt speed: Projectile speed of X takes 5 seconds to go 300 distance units.
@@ -6415,31 +6405,41 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
return false;
uint8 anim = spells[spell_id].CastingAnim;
int bolt_id = -1;
int slot = -1;
//Make sure there is an avialable bolt to be cast.
for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) {
if (projectile_spell_id[i] == 0){
bolt_id = i;
if (ProjectileAtk[i].target_id == 0){
slot = i;
break;
}
}
if (bolt_id < 0)
if (slot < 0)
return false;
if (CheckLosFN(spell_target)) {
projectile_spell_id[bolt_id] = spell_id;
projectile_target_id[bolt_id] = spell_target->GetID();
projectile_x[bolt_id] = GetX(), projectile_y[bolt_id] = GetY(), projectile_z[bolt_id] = GetZ();
projectile_increment[bolt_id] = 1;
projectile_timer.Start(250);
float speed_mod = speed * 0.45f; //Constant for adjusting speeds to match calculated impact time.
float distance = spell_target->CalculateDistance(GetX(), GetY(), GetZ());
float hit = 60.0f + (distance / speed_mod);
ProjectileAtk[slot].increment = 1;
ProjectileAtk[slot].hit_increment = static_cast<uint16>(hit); //This projected hit time if target does NOT MOVE
ProjectileAtk[slot].target_id = spell_target->GetID();
ProjectileAtk[slot].wpn_dmg = spell_id; //Store spell_id in weapon damage field
ProjectileAtk[slot].origin_x = GetX();
ProjectileAtk[slot].origin_y = GetY();
ProjectileAtk[slot].origin_z = GetZ();
ProjectileAtk[slot].skill = SkillConjuration;
ProjectileAtk[slot].speed_mod = speed_mod;
SetProjectileAttack(true);
}
//This will use the correct graphic as defined in the player_1 field of spells_new table. Found in UF+ spell files.
if (RuleB(Spells, UseLiveSpellProjectileGFX)) {
ProjectileAnimation(spell_target,0, false, 1.5,0,0,0, spells[spell_id].player_1);
ProjectileAnimation(spell_target,0, false, speed,0,0,0, spells[spell_id].player_1);
}
//This allows limited support for server using older spell files that do not contain data for bolt graphics.
@@ -6449,19 +6449,17 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id){
if (IsClient()){
if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic.
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, 1.5);
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, speed);
else
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, 1.5);
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, speed);
}
else
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, 1.5);
ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_NPC)), false, speed);
}
//Default to an arrow if not using a mage bolt (Use up to date spell file and enable above rules for best results)
else
ProjectileAnimation(spell_target,0, 1, 1.5);
ProjectileAnimation(spell_target,0, 1, speed);
}
if (spells[spell_id].CastingAnim == 64)
+28 -24
View File
@@ -66,20 +66,19 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
and not SpellFinished().
*/
#include "../common/debug.h"
#include "../common/spdat.h"
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/moremath.h"
#include "../common/item.h"
#include "worldserver.h"
#include "../common/skills.h"
#include "../common/bodytypes.h"
#include "../common/classes.h"
#include "../common/debug.h"
#include "../common/item.h"
#include "../common/rulesys.h"
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/string_util.h"
#include <math.h>
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include <assert.h>
#include <math.h>
#ifndef WIN32
#include <stdlib.h>
@@ -90,8 +89,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#include "../common/packet_dump_file.h"
#endif
#include "string_ids.h"
#include "quest_parser_collection.h"
extern Zone* zone;
extern volatile bool ZoneLoaded;
@@ -180,7 +178,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
if(IsClient()){
int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id);
if (MakeRandomInt(0,99) < chance){
if (zone->random.Roll(chance)) {
Message_StringID(13, SILENCED_STRING);
if(IsClient())
CastToClient()->SendSpellBarEnable(spell_id);
@@ -699,7 +697,7 @@ bool Client::CheckFizzle(uint16 spell_id)
specialize = specialize * 1.3;
break;
}
if(((specialize/6.0f) + 15.0f) < MakeRandomFloat(0, 100)) {
if(((specialize/6.0f) + 15.0f) < zone->random.Real(0, 100)) {
specialize *= SPECIALIZE_FIZZLE / 200.0f;
} else {
specialize = 0.0f;
@@ -741,7 +739,7 @@ bool Client::CheckFizzle(uint16 spell_id)
}
*/
float fizzle_roll = MakeRandomFloat(0, 100);
float fizzle_roll = zone->random.Real(0, 100);
mlog(SPELLS__CASTING, "Check Fizzle %s spell %d fizzlechance: %0.2f%% diff: %0.2f roll: %0.2f", GetName(), spell_id, fizzlechance, diff, fizzle_roll);
@@ -1030,7 +1028,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
mlog(SPELLS__CASTING, "Checking Interruption: spell x: %f spell y: %f cur x: %f cur y: %f channelchance %f channeling skill %d\n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(SkillChanneling));
if(!spells[spell_id].uninterruptable && MakeRandomFloat(0, 100) > channelchance) {
if(!spells[spell_id].uninterruptable && zone->random.Real(0, 100) > channelchance) {
mlog(SPELLS__CASTING_ERR, "Casting of %d canceled: interrupted.", spell_id);
InterruptSpell();
return;
@@ -1046,7 +1044,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
// first check for component reduction
if(IsClient()) {
int reg_focus = CastToClient()->GetFocusEffect(focusReagentCost,spell_id);
if(MakeRandomInt(1, 100) <= reg_focus) {
if(zone->random.Roll(reg_focus)) {
mlog(SPELLS__CASTING, "Spell %d: Reagent focus item prevented reagent consumption (%d chance)", spell_id, reg_focus);
} else {
if(reg_focus > 0)
@@ -1670,6 +1668,12 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
} else {
spell_target = this;
}
if (spell_target && spell_target->IsPet() && spells[spell_id].targettype == ST_GroupNoPets){
Message_StringID(13,NO_CAST_ON_PET);
return false;
}
CastAction = GroupSpell;
break;
}
@@ -3806,7 +3810,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r
void Corpse::CastRezz(uint16 spellid, Mob* Caster)
{
_log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,IsRezzed(),rezzexp);
_log(SPELLS__REZ, "Corpse::CastRezz spellid %i, Rezzed() is %i, rezzexp is %i", spellid,IsRezzed(),rez_experience);
if(IsRezzed()){
if(Caster && Caster->IsClient())
@@ -3825,7 +3829,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster)
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RezzRequest, sizeof(Resurrect_Struct));
Resurrect_Struct* rezz = (Resurrect_Struct*) outapp->pBuffer;
// Why are we truncating these names to 30 characters ?
memcpy(rezz->your_name,this->orgname,30);
memcpy(rezz->your_name,this->corpse_name,30);
memcpy(rezz->corpse_name,this->name,30);
memcpy(rezz->rezzer_name,Caster->GetName(),30);
rezz->zone_id = zone->GetZoneID();
@@ -3838,7 +3842,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster)
rezz->unknown020 = 0x00000000;
rezz->unknown088 = 0x00000000;
// We send this to world, because it needs to go to the player who may not be in this zone.
worldserver.RezzPlayer(outapp, rezzexp, corpse_db_id, OP_RezzRequest);
worldserver.RezzPlayer(outapp, rez_experience, corpse_db_id, OP_RezzRequest);
_pkt(SPELLS__REZ, outapp);
safe_delete(outapp);
}
@@ -4200,7 +4204,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
{
IsFear = true;
int fear_resist_bonuses = CalcFearResistChance();
if(MakeRandomInt(0, 99) < fear_resist_bonuses)
if(zone->random.Roll(fear_resist_bonuses))
{
mlog(SPELLS__RESISTS, "Resisted spell in fear resistance, had %d chance to resist", fear_resist_bonuses);
return 0;
@@ -4211,14 +4215,14 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
//Check for Spell Effect specific resistance chances (ie AA Mental Fortitude)
int se_resist_bonuses = GetSpellEffectResistChance(spell_id);
if(se_resist_bonuses && (MakeRandomInt(0, 99) < se_resist_bonuses))
if(se_resist_bonuses && zone->random.Roll(se_resist_bonuses))
{
return 0;
}
// Check for Chance to Resist Spell bonuses (ie Sanctification Discipline)
int resist_bonuses = CalcResistChanceBonus();
if(resist_bonuses && (MakeRandomInt(0, 99) < resist_bonuses))
if(resist_bonuses && zone->random.Roll(resist_bonuses))
{
mlog(SPELLS__RESISTS, "Resisted spell in sanctification, had %d chance to resist", resist_bonuses);
return 0;
@@ -4444,7 +4448,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
}
//Finally our roll
int roll = MakeRandomInt(0, 200);
int roll = zone->random.Int(0, 200);
if(roll > resist_chance)
{
return 100;
@@ -4661,7 +4665,7 @@ void Mob::Stun(int duration)
if(IsValidSpell(casting_spell_id) && !spells[casting_spell_id].uninterruptable) {
int persistent_casting = spellbonuses.PersistantCasting + itembonuses.PersistantCasting + aabonuses.PersistantCasting;
if(MakeRandomInt(0,99) > persistent_casting)
if(zone->random.Int(0,99) > persistent_casting)
InterruptSpell();
}
+6 -1
View File
@@ -264,6 +264,7 @@
#define TRADESKILL_MISSING_COMPONENTS 3456 //Sorry, but you don't have everything you need for this recipe in your general inventory.
#define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1!
#define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end.
#define NO_CAST_ON_PET 4045 //You cannot cast this spell on your pet.
#define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again.
#define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can!
#define CORPSEDRAG_ALREADY 4062 //You are already dragging %1.
@@ -295,6 +296,9 @@
#define GUILD_BANK_FULL 6098 // There is no more room in the Guild Bank.
#define GUILD_BANK_TRANSFERRED 6100 // '%1' transferred to Guild Bank from Deposits.
#define GUILD_BANK_EMPTY_HANDS 6108 // You must empty your hands to withdraw from the Guild Bank.
#define TRANSFORM_FAILED 6326 //This mold cannot be applied to your %1.
#define TRANSFORM_COMPLETE 6327 //You have successfully transformed your %1.
#define DETRANSFORM_FAILED 6341 //%1 has no transformation that can be removed.
#define GENERIC_STRING 6688 //%1 (used to any basic message)
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
@@ -392,7 +396,8 @@
#define SONG_ENDS_OTHER 12688 //%1's song ends.
#define SONG_ENDS_ABRUPTLY_OTHER 12689 //%1's song ends abruptly.
#define DIVINE_AURA_NO_ATK 12695 //You can't attack while invulnerable!
#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive.
#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive
#define RANGED_TOO_CLOSE 12698 //Your target is too close to use a ranged weapon!
#define BACKSTAB_WEAPON 12874 //You need a piercing weapon as your primary weapon in order to backstab
#define MORE_SKILLED_THAN_I 12931 //%1 tells you, 'You are more skilled than I! What could I possibly teach you?'
#define SURNAME_EXISTS 12939 //You already have a surname. Operation failed.
+48 -13
View File
@@ -24,17 +24,14 @@
#include <netinet/in.h> //for htonl
#endif
#include "masterentity.h"
#include "zonedb.h"
#include "../common/packet_functions.h"
#include "../common/packet_dump.h"
#include "titles.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "quest_parser_collection.h"
#include "../common/string_util.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "titles.h"
#include "zonedb.h"
extern QueryServ* QServ;
@@ -283,6 +280,44 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
}
container = inst;
if (container->GetItem() && container->GetItem()->BagType == BagTypeTransformationmold) {
const ItemInst* inst = container->GetItem(0);
bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation);
if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) {
const Item_Struct* new_weapon = inst->GetItem();
user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true);
container->Clear();
user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->IsInstNoDrop(), MainCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2));
user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name);
if (RuleB(Inventory, DeleteTransformationMold))
user->DeleteItemInInventory(in_combine->container_slot, 0, true);
}
else if (inst) {
user->Message_StringID(4, TRANSFORM_FAILED, inst->GetItem()->Name);
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
if (container->GetItem() && container->GetItem()->BagType == BagTypeDetransformationmold) {
const ItemInst* inst = container->GetItem(0);
if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) {
const Item_Struct* new_weapon = inst->GetItem();
user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true);
container->Clear();
user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->IsInstNoDrop(), MainCursor, 0, 0);
user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name);
}
else if (inst) {
user->Message_StringID(4, DETRANSFORM_FAILED, inst->GetItem()->Name);
}
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
user->QueuePacket(outapp);
safe_delete(outapp);
return;
}
DBTradeskillRecipe_Struct spec;
if (!database.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) {
@@ -888,7 +923,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
_log(TRADESKILLS__TRACE, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance);
_log(TRADESKILLS__TRACE, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR());
float res = MakeRandomFloat(0, 99);
float res = zone->random.Real(0, 99);
int aa_chance = 0;
//AA modifiers
@@ -1022,7 +1057,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
chance = mod_tradeskill_chance(chance, spec);
if (((spec->tradeskill==75) || GetGM() || (chance > res)) || MakeRandomInt(0, 99) < aa_chance){
if (((spec->tradeskill==75) || GetGM() || (chance > res)) || zone->random.Roll(aa_chance)) {
success_modifier = 1;
if(over_trivial < 0)
@@ -1092,7 +1127,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
uint8 sc = 0;
while(itr != spec->salvage.end()) {
for(sc = 0; sc < itr->second; sc++)
if(MakeRandomInt(0,99) < SalvageChance)
if(zone->random.Roll(SalvageChance))
SummonItem(itr->first, 1);
++itr;
}
@@ -1118,7 +1153,7 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float
//In stage2 the only thing that matters is your current unmodified skill.
//If you want to customize here you probbably need to implement your own
//formula instead of tweaking the below one.
if (chance_stage1 > MakeRandomFloat(0, 99)) {
if (chance_stage1 > zone->random.Real(0, 99)) {
if (current_raw_skill < 15) {
//Always succeed
chance_stage2 = 100;
@@ -1133,7 +1168,7 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float
chance_stage2 = mod_tradeskill_skillup(chance_stage2);
if (chance_stage2 > MakeRandomFloat(0, 99)) {
if (chance_stage2 > zone->random.Real(0, 99)) {
//Only if stage1 and stage2 succeeded you get a skillup.
SetSkill(tradeskill, current_raw_skill + 1);
+7 -7
View File
@@ -142,7 +142,7 @@ void Trap::Trigger(Mob* trigger)
{
if ((tmp = database.GetNPCType(effectvalue)))
{
auto randomOffset = xyz_heading(-5 + MakeRandomInt(0, 10),-5 + MakeRandomInt(0, 10),-5 + MakeRandomInt(0, 10), MakeRandomInt(0, 249));
auto randomOffset = xyz_heading(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + m_Position;
NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
new_npc->AddLootTable();
@@ -165,7 +165,7 @@ void Trap::Trigger(Mob* trigger)
{
if ((tmp = database.GetNPCType(effectvalue)))
{
auto randomOffset = xyz_heading(-2 + MakeRandomInt(0, 5), -2 + MakeRandomInt(0, 5), -2 + MakeRandomInt(0, 5), MakeRandomInt(0, 249));
auto randomOffset = xyz_heading(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249));
auto spawnPosition = randomOffset + m_Position;
NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
new_npc->AddLootTable();
@@ -187,10 +187,10 @@ void Trap::Trigger(Mob* trigger)
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
int dmg = MakeRandomInt(effectvalue, effectvalue2);
int dmg = zone->random.Int(effectvalue, effectvalue2);
trigger->SetHP(trigger->GetHP() - dmg);
a->damage = dmg;
a->sequence = MakeRandomInt(0, 1234567);
a->sequence = zone->random.Int(0, 1234567);
a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID();
a->spellid = 0;
a->target = trigger->GetID();
@@ -199,7 +199,7 @@ void Trap::Trigger(Mob* trigger)
safe_delete(outapp);
}
}
respawn_timer.Start((respawn_time + MakeRandomInt(0, respawn_var)) * 1000);
respawn_timer.Start((respawn_time + zone->random.Int(0, respawn_var)) * 1000);
chkarea_timer.Disable();
disarmed = true;
}
@@ -243,8 +243,8 @@ Mob* EntityList::GetTrapTrigger(Trap* trap) {
if ((diff.m_X*diff.m_X + diff.m_Y*diff.m_Y) <= maxdist
&& diff.m_Z < trap->maxzdiff)
{
if (MakeRandomInt(0,100) < trap->chance)
return cur;
if (zone->random.Roll(trap->chance))
return(cur);
else
savemob = cur;
}
+332
View File
@@ -0,0 +1,332 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "../common/types.h"
#include "entity.h"
#include "masterentity.h"
#include "../common/spdat.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
/*
Schema:
CREATE TABLE traps (
id int(11) NOT NULL auto_increment,
zone varchar(16) NOT NULL default '',
x int(11) NOT NULL default '0',
y int(11) NOT NULL default '0',
z int(11) NOT NULL default '0',
chance tinyint NOT NULL default '0',
maxzdiff float NOT NULL default '0',
radius float NOT NULL default '0',
effect int(11) NOT NULL default '0',
effectvalue int(11) NOT NULL default '0',
effectvalue2 int(11) NOT NULL default '0',
message varcahr(200) NOT NULL;
skill int(11) NOT NULL default '0',
spawnchance int(11) NOT NULL default '0',
PRIMARY KEY (id)
) TYPE=MyISAM;
*/
Trap::Trap() :
Entity(),
respawn_timer(600000),
chkarea_timer(500),
m_Position(xyz_location::Origin())
{
trap_id = 0;
maxzdiff = 0;
radius = 0;
effect = 0;
effectvalue = 0;
effectvalue2 = 0;
skill = 0;
level = 0;
respawn_timer.Disable();
detected = false;
disarmed = false;
respawn_time = 0;
respawn_var = 0;
hiddenTrigger = nullptr;
ownHiddenTrigger = false;
}
Trap::~Trap()
{
//don't need to clean up mob as traps are always cleaned up same time as NPCs
//cleaning up mob here can actually cause a crash via race condition
}
bool Trap::Process()
{
if (chkarea_timer.Enabled() && chkarea_timer.Check()
/*&& zone->GetClientCount() > 0*/ )
{
Mob* trigger = entity_list.GetTrapTrigger(this);
if (trigger && !(trigger->IsClient() && trigger->CastToClient()->GetGM()))
{
Trigger(trigger);
}
}
if (respawn_timer.Enabled() && respawn_timer.Check())
{
detected = false;
disarmed = false;
chkarea_timer.Enable();
respawn_timer.Disable();
}
return true;
}
void Trap::Trigger(Mob* trigger)
{
int i = 0;
const NPCType* tmp = 0;
switch (effect)
{
case trapTypeDebuff:
if(message.empty())
{
entity_list.MessageClose(trigger,false,100,13,"%s triggers a trap!",trigger->GetName());
}
else
{
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
}
if(hiddenTrigger){
hiddenTrigger->SpellFinished(effectvalue, trigger, 10, 0, -1, spells[effectvalue].ResistDiff);
}
break;
case trapTypeAlarm:
if (message.empty())
{
entity_list.MessageClose(trigger,false,effectvalue,13,"A loud alarm rings out through the air...");
}
else
{
entity_list.MessageClose(trigger,false,effectvalue,13,"%s",message.c_str());
}
entity_list.SendAlarm(this,trigger,effectvalue);
break;
case trapTypeMysticSpawn:
if (message.empty())
{
entity_list.MessageClose(trigger,false,100,13,"The air shimmers...");
}
else
{
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
}
for (i = 0; i < effectvalue2; i++)
{
if ((tmp = database.GetNPCType(effectvalue)))
{
<<<<<<< HEAD
auto randomOffset = xyz_heading(-5 + MakeRandomInt(0, 10),-5 + MakeRandomInt(0, 10),-5 + MakeRandomInt(0, 10), MakeRandomInt(0, 249));
auto spawnPosition = randomOffset + m_Position;
NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
=======
NPC* new_npc = new NPC(tmp, 0, x-5+zone->random.Int(0, 10), y-5+zone->random.Int(0, 10), z-5+zone->random.Int(0, 10), zone->random.Int(0, 249), FlyMode3);
>>>>>>> master
new_npc->AddLootTable();
entity_list.AddNPC(new_npc);
new_npc->AddToHateList(trigger,1);
}
}
break;
case trapTypeBanditSpawn:
if (message.empty())
{
entity_list.MessageClose(trigger,false,100,13,"A bandit leaps out from behind a tree!");
}
else
{
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
}
for (i = 0; i < effectvalue2; i++)
{
if ((tmp = database.GetNPCType(effectvalue)))
{
<<<<<<< HEAD
auto randomOffset = xyz_heading(-2 + MakeRandomInt(0, 5), -2 + MakeRandomInt(0, 5), -2 + MakeRandomInt(0, 5), MakeRandomInt(0, 249));
auto spawnPosition = randomOffset + m_Position;
NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
=======
NPC* new_npc = new NPC(tmp, 0, x-2+zone->random.Int(0, 5), y-2+zone->random.Int(0, 5), z-2+zone->random.Int(0, 5), zone->random.Int(0, 249), FlyMode3);
>>>>>>> master
new_npc->AddLootTable();
entity_list.AddNPC(new_npc);
new_npc->AddToHateList(trigger,1);
}
}
break;
case trapTypeDamage:
if (message.empty())
{
entity_list.MessageClose(trigger,false,100,13,"%s triggers a trap!",trigger->GetName());
}
else
{
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
}
if(trigger->IsClient())
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
int dmg = zone->random.Int(effectvalue, effectvalue2);
trigger->SetHP(trigger->GetHP() - dmg);
a->damage = dmg;
a->sequence = zone->random.Int(0, 1234567);
a->source = GetHiddenTrigger()!=nullptr ? GetHiddenTrigger()->GetID() : trigger->GetID();
a->spellid = 0;
a->target = trigger->GetID();
a->type = 253;
trigger->CastToClient()->QueuePacket(outapp);
safe_delete(outapp);
}
}
respawn_timer.Start((respawn_time + zone->random.Int(0, respawn_var)) * 1000);
chkarea_timer.Disable();
disarmed = true;
}
Trap* EntityList::FindNearbyTrap(Mob* searcher, float max_dist) {
float dist = 999999;
Trap* current_trap = nullptr;
float max_dist2 = max_dist*max_dist;
Trap *cur;
for (auto it = trap_list.begin(); it != trap_list.end(); ++it) {
cur = it->second;
if(cur->disarmed)
continue;
auto diff = searcher->GetPosition() - cur->m_Position;
float curdist = diff.m_X * diff.m_X + diff.m_Y * diff.m_Y + diff.m_Z * diff.m_Z;
if (curdist < max_dist2 && curdist < dist)
{
dist = curdist;
current_trap = cur;
}
}
return current_trap;
}
Mob* EntityList::GetTrapTrigger(Trap* trap) {
Mob* savemob = 0;
float maxdist = trap->radius * trap->radius;
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
Client* cur = it->second;
auto diff = cur->GetPosition() - trap->m_Position;
diff.ABS_XYZ();
if ((diff.m_X*diff.m_X + diff.m_Y*diff.m_Y) <= maxdist
&& diff.m_Z < trap->maxzdiff)
{
<<<<<<< HEAD
if (MakeRandomInt(0,100) < trap->chance)
return cur;
=======
if (zone->random.Roll(trap->chance))
return(cur);
>>>>>>> master
else
savemob = cur;
}
}
return savemob;
}
//todo: rewrite this to not need direct access to trap members.
bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
std::string query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
"maxzdiff, radius, chance, message, respawn_time, respawn_var, level "
"FROM traps WHERE zone='%s' AND version=%u", zonename, version);
auto results = QueryDatabase(query);
if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in LoadTraps query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
Trap* trap = new Trap();
trap->trap_id = atoi(row[0]);
trap->m_Position = xyz_location(atof(row[1]), atof(row[2]), atof(row[3]));
trap->effect = atoi(row[4]);
trap->effectvalue = atoi(row[5]);
trap->effectvalue2 = atoi(row[6]);
trap->skill = atoi(row[7]);
trap->maxzdiff = atof(row[8]);
trap->radius = atof(row[9]);
trap->chance = atoi(row[10]);
trap->message = row[11];
trap->respawn_time = atoi(row[12]);
trap->respawn_var = atoi(row[13]);
trap->level = atoi(row[14]);
entity_list.AddTrap(trap);
trap->CreateHiddenTrigger();
}
return true;
}
void Trap::CreateHiddenTrigger()
{
if(hiddenTrigger)
return;
const NPCType *base_type = database.GetNPCType(500);
NPCType *make_npc = new NPCType;
memcpy(make_npc, base_type, sizeof(NPCType));
make_npc->max_hp = 100000;
make_npc->cur_hp = 100000;
strcpy(make_npc->name, "a_trap");
make_npc->runspeed = 0.0f;
make_npc->bodytype = BT_Special;
make_npc->race = 127;
make_npc->gender = 0;
make_npc->loottable_id = 0;
make_npc->npc_spells_id = 0;
make_npc->d_meele_texture1 = 0;
make_npc->d_meele_texture2 = 0;
make_npc->trackable = 0;
make_npc->level = level;
strcpy(make_npc->special_abilities, "19,1^20,1^24,1^25,1");
NPC* npca = new NPC(make_npc, nullptr, xyz_heading(m_Position, 0.0f), FlyMode3);
npca->GiveNPCTypeData(make_npc);
entity_list.AddNPC(npca);
hiddenTrigger = npca;
ownHiddenTrigger = true;
}
+14 -18
View File
@@ -19,21 +19,17 @@
#ifdef _EQDEBUG
#include <iostream>
#endif
//#include <iomanip>
#include <stdlib.h>
#include <math.h>
#include "npc.h"
#include "masterentity.h"
#include "npc_ai.h"
#include "map.h"
#include "water_map.h"
#include "../common/moremath.h"
#include "string_ids.h"
#include "../common/misc_functions.h"
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/features.h"
#include "../common/misc_functions.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "map.h"
#include "npc.h"
#include "quest_parser_collection.h"
#include "water_map.h"
#include <math.h>
#include <stdlib.h>
struct wp_distance
{
@@ -265,7 +261,7 @@ void NPC::CalculateNewWaypoint()
if(closest.size() != 0)
{
iter = closest.begin();
std::advance(iter, MakeRandomInt(0, closest.size() - 1));
std::advance(iter, zone->random.Int(0, closest.size() - 1));
cur_wp = (*iter).index;
}
@@ -273,7 +269,7 @@ void NPC::CalculateNewWaypoint()
}
case 2: //random
{
cur_wp = MakeRandomInt(0, Waypoints.size() - 1);
cur_wp = zone->random.Int(0, Waypoints.size() - 1);
if(cur_wp == old_wp)
{
if(cur_wp == (Waypoints.size() - 1))
@@ -334,7 +330,7 @@ void NPC::CalculateNewWaypoint()
if(closest.size() != 0)
{
iter = closest.begin();
std::advance(iter, MakeRandomInt(0, closest.size() - 1));
std::advance(iter, zone->random.Int(0, closest.size() - 1));
cur_wp = (*iter).index;
}
break;
@@ -407,13 +403,13 @@ void NPC::SetWaypointPause()
switch (pausetype)
{
case 0: //Random Half
AIwalking_timer->Start((cur_wp_pause - MakeRandomInt(0, cur_wp_pause-1)/2)*1000);
AIwalking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000);
break;
case 1: //Full
AIwalking_timer->Start(cur_wp_pause*1000);
break;
case 2: //Random Full
AIwalking_timer->Start(MakeRandomInt(0, cur_wp_pause-1)*1000);
AIwalking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000);
break;
}
}
+1 -1
View File
@@ -705,7 +705,7 @@ void WorldServer::Process() {
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
// I don't know why Rezzed is not set to true in CompleteRezz().
corpse->IsRezzed(true);
corpse->CompleteRezz();
corpse->CompleteResurrection();
}
}
+1 -3
View File
@@ -20,12 +20,10 @@
#include "../common/worldconn.h"
#include "../common/eq_packet_structs.h"
#include <string>
struct GuildJoin_Struct;
class ServerPacket;
class EQApplicationPacket;
class Client;
class Database;
class WorldServer : public WorldConnection {
public:
+31 -38
View File
@@ -15,17 +15,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <float.h>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <time.h>
#include <math.h>
#ifdef _WINDOWS
#include <process.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#else
@@ -33,31 +30,26 @@
#include "../common/unix.h"
#endif
#include "masterentity.h"
#include "../common/debug.h"
#include "../common/features.h"
#include "spawngroup.h"
#include "spawn2.h"
#include "zone.h"
#include "worldserver.h"
#include "npc.h"
#include "net.h"
#include "../common/seperator.h"
#include "../common/packet_dump_file.h"
#include "../common/eq_stream_factory.h"
#include "../common/eq_stream.h"
#include "../common/string_util.h"
#include "zone_config.h"
#include "../common/breakdowns.h"
#include "map.h"
#include "water_map.h"
#include "object.h"
#include "petitions.h"
#include "pathing.h"
#include "event_codes.h"
#include "client_logs.h"
#include "../common/rulesys.h"
#include "../common/seperator.h"
#include "../common/string_util.h"
#include "client_logs.h"
#include "guild_mgr.h"
#include "map.h"
#include "net.h"
#include "npc.h"
#include "object.h"
#include "pathing.h"
#include "petitions.h"
#include "quest_parser_collection.h"
#include "spawn2.h"
#include "spawngroup.h"
#include "water_map.h"
#include "worldserver.h"
#include "zone_config.h"
#include "zone.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -65,18 +57,19 @@
#define strcasecmp _stricmp
#endif
extern bool staticzone;
extern NetConnection net;
extern PetitionList petition_list;
extern QuestParserCollection* parse;
extern uint16 adverrornum;
extern uint32 numclients;
extern WorldServer worldserver;
extern Zone* zone;
extern uint32 numclients;
extern NetConnection net;
extern uint16 adverrornum;
extern PetitionList petition_list;
Mutex MZoneShutdown;
extern bool staticzone;
Zone* zone = 0;
volatile bool ZoneLoaded = false;
extern QuestParserCollection* parse;
Zone* zone = 0;
bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
const char* zonename = database.GetZoneName(iZoneID);
@@ -1301,13 +1294,13 @@ void Zone::ChangeWeather()
return;
}
int chance = MakeRandomInt(0, 3);
int chance = zone->random.Int(0, 3);
uint8 rainchance = zone->newzone_data.rain_chance[chance];
uint8 rainduration = zone->newzone_data.rain_duration[chance];
uint8 snowchance = zone->newzone_data.snow_chance[chance];
uint8 snowduration = zone->newzone_data.snow_duration[chance];
uint32 weathertimer = 0;
uint16 tmpweather = MakeRandomInt(0, 100);
uint16 tmpweather = zone->random.Int(0, 100);
uint8 duration = 0;
uint8 tmpOldWeather = zone->zone_weather;
bool changed = false;
@@ -1316,7 +1309,7 @@ void Zone::ChangeWeather()
{
if(rainchance > 0 || snowchance > 0)
{
uint8 intensity = MakeRandomInt(1, 10);
uint8 intensity = zone->random.Int(1, 10);
if((rainchance > snowchance) || (rainchance == snowchance))
{
//It's gunna rain!
+11 -21
View File
@@ -18,25 +18,14 @@
#ifndef ZONE_H
#define ZONE_H
#include "../common/mutex.h"
#include "../common/linked_list.h"
#include "../common/types.h"
#include "../common/eqtime.h"
#include "../common/servertalk.h"
#include "../common/linked_list.h"
#include "../common/rulesys.h"
#include "../common/eq_packet_structs.h"
#include "../common/features.h"
#include "spawngroup.h"
//#include "mob.h"
#include "zonedump.h"
#include "spawn2.h"
#include "tasks.h"
#include "pathing.h"
#include "../common/types.h"
#include "../common/random.h"
#include "qglobals.h"
#include <unordered_map>
class Map;
class WaterMap;
#include "spawn2.h"
#include "spawngroup.h"
struct ZonePoint
{
@@ -78,12 +67,10 @@ struct item_tick_struct {
std::string qglobal;
};
extern EntityList entity_list;
class database;
class Map;
class WaterMap;
class PathManager;
struct SendAA_Struct;
class database;
extern EntityList entity_list;
class Zone
{
@@ -262,6 +249,9 @@ public:
void UpdateHotzone();
std::unordered_map<int, item_tick_struct> tick_items;
// random object that provides random values for the zone
EQEmu::Random random;
//MODDING HOOKS
void mod_init();
void mod_repop();
+47 -62
View File
@@ -1,21 +1,16 @@
#include "zonedb.h"
#include "../common/item.h"
#include "../common/string_util.h"
#include "../common/extprofile.h"
#include "../common/guilds.h"
#include "../common/item.h"
#include "../common/rulesys.h"
#include "../common/rdtsc.h"
#include "zone.h"
#include "corpse.h"
#include "../common/string_util.h"
#include "client.h"
#include "merc.h"
#include "corpse.h"
#include "groups.h"
#include "raids.h"
#include <iostream>
#include <string>
#include <sstream>
#include "merc.h"
#include "zone.h"
#include "zonedb.h"
#include <ctime>
#include <iostream>
extern Zone* zone;
@@ -3368,7 +3363,7 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){
auto results = QueryDatabase(query);
auto row = results.begin();
if (results.Success() && results.RowsAffected() != 0){
return atoll(row[0]);
return atoul(row[0]);
}
return 0;
}
@@ -3501,7 +3496,7 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) {
for (auto row = results.begin(); row != results.end(); ++row) {
for (int i = 0; i < corpse; i++) {
return atoll(row[0]);
return atoul(row[0]);
}
}
return 0;
@@ -3525,7 +3520,7 @@ uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) {
if (tmp) {
itemid = tmp->GetWornItem(slotid);
tmp->DepopCorpse();
tmp->DepopPlayerCorpse();
}
return itemid;
}
@@ -3575,7 +3570,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
uint16 i = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
pcs->locked = atoi(row[i++]); // is_locked,
pcs->exp = atoll(row[i++]); // exp,
pcs->exp = atoul(row[i++]); // exp,
pcs->size = atoi(row[i++]); // size,
pcs->level = atoi(row[i++]); // `level`,
pcs->race = atoi(row[i++]); // race,
@@ -3584,10 +3579,10 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
pcs->deity = atoi(row[i++]); // deity,
pcs->texture = atoi(row[i++]); // texture,
pcs->helmtexture = atoi(row[i++]); // helm_texture,
pcs->copper = atoll(row[i++]); // copper,
pcs->silver = atoll(row[i++]); // silver,
pcs->gold = atoll(row[i++]); // gold,
pcs->plat = atoll(row[i++]); // platinum,
pcs->copper = atoul(row[i++]); // copper,
pcs->silver = atoul(row[i++]); // silver,
pcs->gold = atoul(row[i++]); // gold,
pcs->plat = atoul(row[i++]); // platinum,
pcs->haircolor = atoi(row[i++]); // hair_color,
pcs->beardcolor = atoi(row[i++]); // beard_color,
pcs->eyecolor1 = atoi(row[i++]); // eye_color_1,
@@ -3595,18 +3590,18 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
pcs->hairstyle = atoi(row[i++]); // hair_style,
pcs->face = atoi(row[i++]); // face,
pcs->beard = atoi(row[i++]); // beard,
pcs->drakkin_heritage = atoll(row[i++]); // drakkin_heritage,
pcs->drakkin_tattoo = atoll(row[i++]); // drakkin_tattoo,
pcs->drakkin_details = atoll(row[i++]); // drakkin_details,
pcs->item_tint[0].color = atoll(row[i++]); // wc_1,
pcs->item_tint[1].color = atoll(row[i++]); // wc_2,
pcs->item_tint[2].color = atoll(row[i++]); // wc_3,
pcs->item_tint[3].color = atoll(row[i++]); // wc_4,
pcs->item_tint[4].color = atoll(row[i++]); // wc_5,
pcs->item_tint[5].color = atoll(row[i++]); // wc_6,
pcs->item_tint[6].color = atoll(row[i++]); // wc_7,
pcs->item_tint[7].color = atoll(row[i++]); // wc_8,
pcs->item_tint[8].color = atoll(row[i++]); // wc_9
pcs->drakkin_heritage = atoul(row[i++]); // drakkin_heritage,
pcs->drakkin_tattoo = atoul(row[i++]); // drakkin_tattoo,
pcs->drakkin_details = atoul(row[i++]); // drakkin_details,
pcs->item_tint[0].color = atoul(row[i++]); // wc_1,
pcs->item_tint[1].color = atoul(row[i++]); // wc_2,
pcs->item_tint[2].color = atoul(row[i++]); // wc_3,
pcs->item_tint[3].color = atoul(row[i++]); // wc_4,
pcs->item_tint[4].color = atoul(row[i++]); // wc_5,
pcs->item_tint[5].color = atoul(row[i++]); // wc_6,
pcs->item_tint[6].color = atoul(row[i++]); // wc_7,
pcs->item_tint[7].color = atoul(row[i++]); // wc_8,
pcs->item_tint[8].color = atoul(row[i++]); // wc_9
}
query = StringFormat(
"SELECT \n"
@@ -3622,7 +3617,6 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
"FROM \n"
"character_corpse_items \n"
"WHERE `corpse_id` = %u\n"
// "ORDER BY `equip_slot`"
,
corpse_id
);
@@ -3634,7 +3628,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
for (auto row = results.begin(); row != results.end(); ++row) {
memset(&pcs->items[i], 0, sizeof (player_lootitem::ServerLootItem_Struct));
pcs->items[i].equip_slot = atoi(row[r++]); // equip_slot,
pcs->items[i].item_id = atoll(row[r++]); // item_id,
pcs->items[i].item_id = atoul(row[r++]); // item_id,
pcs->items[i].charges = atoi(row[r++]); // charges,
pcs->items[i].aug_1 = atoi(row[r++]); // aug_1,
pcs->items[i].aug_2 = atoi(row[r++]); // aug_2,
@@ -3658,8 +3652,8 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
corpse = Corpse::LoadFromDBData(
atoll(row[0]), // uint32 in_dbid
corpse = Corpse::LoadCharacterCorpseEntity(
atoul(row[0]), // uint32 in_dbid
char_id, // uint32 in_charid
row[1], // char* in_charname
position,
@@ -3673,7 +3667,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z
entity_list.AddCorpse(corpse);
corpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
corpse->Spawn();
if (!UnburyCharacterCorpse(corpse->GetDBID(), dest_zone_id, dest_instance_id, position))
if (!UnburyCharacterCorpse(corpse->GetCorpseDBID(), dest_zone_id, dest_instance_id, position))
LogFile->write(EQEMuLog::Error, "Unable to unbury a summoned player corpse for character id %u.", char_id);
}
@@ -3681,7 +3675,7 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z
}
bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id, uint16 dest_instance_id, const xyz_heading& position) {
Corpse* NewCorpse = 0;
Corpse* corpse = nullptr;
int CorpseCount = 0;
std::string query = StringFormat(
@@ -3697,18 +3691,19 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id
results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
NewCorpse = Corpse::LoadFromDBData(
atoll(row[0]),
corpse = Corpse::LoadCharacterCorpseEntity(
atoul(row[0]),
char_id,
row[1],
position,
row[2],
atoi(row[3]) == 1,
false);
if (NewCorpse) {
entity_list.AddCorpse(NewCorpse);
NewCorpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
NewCorpse->Spawn();
if (corpse) {
entity_list.AddCorpse(corpse);
corpse->SetDecayTimer(RuleI(Character, CorpseDecayTimeMS));
corpse->Spawn();
++CorpseCount;
}
else{
@@ -3743,9 +3738,9 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
auto position = xyz_heading(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6]));
NewCorpse = Corpse::LoadFromDBData(
atoll(row[0]), // id uint32 in_dbid
atoll(row[1]), // charid uint32 in_charid
NewCorpse = Corpse::LoadCharacterCorpseEntity(
atoul(row[0]), // id uint32 in_dbid
atoul(row[1]), // charid uint32 in_charid
row[2], // char_name
position,
row[7], // time_of_death char* time_of_death
@@ -3770,9 +3765,9 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) {
for (auto row = results.begin(); row != results.end(); ++row) {
auto position = xyz_heading(atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6]));
entity_list.AddCorpse(
Corpse::LoadFromDBData(
atoll(row[0]), // id uint32 in_dbid
atoll(row[1]), // charid uint32 in_charid
Corpse::LoadCharacterCorpseEntity(
atoul(row[0]), // id uint32 in_dbid
atoul(row[1]), // charid uint32 in_charid
row[2], // char_name
position,
row[7], // time_of_death char* time_of_death
@@ -3793,15 +3788,6 @@ uint32 ZoneDatabase::GetFirstCorpseID(uint32 char_id) {
return 0;
}
bool ZoneDatabase::ClearCorpseItems(uint32 db_id){
std::string query = StringFormat("DELETE FROM `character_corpse_items` WHERE `corpse_id` = %u", db_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
return true;
}
return false;
}
bool ZoneDatabase::DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id){
std::string query = StringFormat("DELETE FROM `character_corpse_items` WHERE `corpse_id` = %u AND equip_slot = %u AND item_id = %u", db_id, equip_slot, item_id);
auto results = QueryDatabase(query);
@@ -3815,7 +3801,6 @@ bool ZoneDatabase::BuryCharacterCorpse(uint32 db_id) {
std::string query = StringFormat("UPDATE `character_corpses` SET `is_buried` = 1 WHERE `id` = %u", db_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
ClearCorpseItems(db_id);
return true;
}
return false;
@@ -3834,8 +3819,8 @@ bool ZoneDatabase::BuryAllCharacterCorpses(uint32 char_id) {
bool ZoneDatabase::DeleteCharacterCorpse(uint32 db_id) {
std::string query = StringFormat("DELETE FROM `character_corpses` WHERE `id` = %d", db_id);
auto results = QueryDatabase(query);
if (results.Success() && results.RowsAffected() != 0){
if (results.Success() && results.RowsAffected() != 0)
return true;
}
return false;
}
+3877
View File
File diff suppressed because it is too large Load Diff
+18 -10
View File
@@ -3,11 +3,25 @@
#include "../common/shareddb.h"
#include "../common/eq_packet_structs.h"
#include "../common/loottable.h"
#include "zonedump.h"
#include "position.h"
#include "../common/faction.h"
#include <limits>
class Client;
class Corpse;
class Merc;
class NPC;
class Petition;
class Spawn2;
class SpawnGroupList;
class ItemInst;
struct CharacterEventLog_Struct;
struct Door;
struct ExtendedProfile_Struct;
struct NPCType;
struct PlayerCorpse_Struct;
struct ZonePoint;
struct npcDecayTimes_Struct;
template <class TYPE> class LinkedList;
//#include "doors.h"
@@ -164,6 +178,7 @@ struct MercInfo {
bool IsSuspended;
uint32 MercTimerRemaining;
uint8 Gender;
float MercSize;
int32 State;
uint32 Stance;
int32 hp;
@@ -198,12 +213,6 @@ struct ClientMercEntry {
uint32 npcid;
};
class ItemInst;
struct FactionMods;
struct FactionValue;
struct LootTable_Struct;
class ZoneDatabase : public SharedDatabase {
typedef std::list<ServerLootItem_Struct*> ItemList;
public:
@@ -292,7 +301,6 @@ public:
bool NoRentExpired(const char* name);
/* Corpses */
bool ClearCorpseItems(uint32 db_id);
bool DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id);
uint32 GetCharacterCorpseItemCount(uint32 corpse_id);
bool LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs);
+519
View File
@@ -0,0 +1,519 @@
#ifndef ZONEDB_H_
#define ZONEDB_H_
#include "../common/shareddb.h"
#include "../common/eq_packet_structs.h"
<<<<<<< HEAD
#include "../common/loottable.h"
#include "zonedump.h"
#include "position.h"
=======
>>>>>>> master
#include "../common/faction.h"
class Client;
class Corpse;
class Merc;
class NPC;
class Petition;
class Spawn2;
class SpawnGroupList;
class ItemInst;
struct CharacterEventLog_Struct;
struct Door;
struct ExtendedProfile_Struct;
struct NPCType;
struct PlayerCorpse_Struct;
struct ZonePoint;
struct npcDecayTimes_Struct;
template <class TYPE> class LinkedList;
//#include "doors.h"
struct wplist {
int index;
float x;
float y;
float z;
int pause;
float heading;
};
#pragma pack(1)
struct DBnpcspells_entries_Struct {
int16 spellid;
uint16 type;
uint8 minlevel;
uint8 maxlevel;
int16 manacost;
int32 recast_delay;
int16 priority;
int16 resist_adjust;
};
#pragma pack()
#pragma pack(1)
struct DBnpcspellseffects_entries_Struct {
int16 spelleffectid;
uint8 minlevel;
uint8 maxlevel;
int32 base;
int32 limit;
int32 max;
};
#pragma pack()
struct DBnpcspells_Struct {
uint32 parent_list;
uint16 attack_proc;
uint8 proc_chance;
uint16 range_proc;
int16 rproc_chance;
uint16 defensive_proc;
int16 dproc_chance;
uint32 numentries;
uint32 fail_recast;
uint32 engaged_no_sp_recast_min;
uint32 engaged_no_sp_recast_max;
uint8 engaged_beneficial_self_chance;
uint8 engaged_beneficial_other_chance;
uint8 engaged_detrimental_chance;
uint32 pursue_no_sp_recast_min;
uint32 pursue_no_sp_recast_max;
uint8 pursue_detrimental_chance;
uint32 idle_no_sp_recast_min;
uint32 idle_no_sp_recast_max;
uint8 idle_beneficial_chance;
DBnpcspells_entries_Struct entries[0];
};
struct DBnpcspellseffects_Struct {
uint32 parent_list;
uint32 numentries;
DBnpcspellseffects_entries_Struct entries[0];
};
struct DBTradeskillRecipe_Struct {
SkillUseTypes tradeskill;
int16 skill_needed;
uint16 trivial;
bool nofail;
bool replace_container;
std::vector< std::pair<uint32,uint8> > onsuccess;
std::vector< std::pair<uint32,uint8> > onfail;
std::vector< std::pair<uint32,uint8> > salvage;
std::string name;
uint8 must_learn;
bool has_learnt;
uint32 madecount;
uint32 recipe_id;
bool quest;
};
struct PetRecord {
uint32 npc_type; // npc_type id for the pet data to use
bool temporary;
int16 petpower;
uint8 petcontrol; // What kind of control over the pet is possible (Animation, familiar, ...)
uint8 petnaming; // How to name the pet (Warder, pet, random name, familiar, ...)
bool monsterflag; // flag for if a random monster appearance should get picked
uint32 equipmentset; // default equipment for the pet
};
// Actual pet info for a client.
struct PetInfo {
uint16 SpellID;
int16 petpower;
uint32 HP;
uint32 Mana;
float size;
SpellBuff_Struct Buffs[BUFF_COUNT];
uint32 Items[EmuConstants::EQUIPMENT_SIZE];
char Name[64];
};
struct ZoneSpellsBlocked {
uint32 spellid;
int8 type;
xyz_location m_Location;
xyz_location m_Difference;
char message[256];
};
struct TraderCharges_Struct {
uint32 ItemID[80];
int32 SerialNumber[80];
uint32 ItemCost[80];
int32 Charges[80];
};
const int MaxMercStanceID = 9;
struct MercStanceInfo {
uint8 ProficiencyID;
uint8 ClassID;
uint32 StanceID;
uint8 IsDefault;
};
struct MercTemplate {
uint32 MercTemplateID;
uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300)
uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan<br>Type: Healer<br>Confidence: High<br>Proficiency: Apprentice, Tier V...
uint16 RaceID;
uint8 ClassID;
uint32 MercNPCID;
uint8 ProficiencyID;
uint8 TierID;
uint8 CostFormula; // To determine cost to client
uint32 ClientVersion; // Only send valid mercs per expansion
uint8 MercNameType; // Determines if merc gets random name or default text
char MercNamePrefix[25];
char MercNameSuffix[25];
uint32 Stances[MaxMercStanceID];
};
struct MercInfo {
uint32 mercid;
uint8 slot;
char merc_name[64];
uint32 MercTemplateID;
const MercTemplate* myTemplate;
uint32 SuspendedTime;
bool IsSuspended;
uint32 MercTimerRemaining;
uint8 Gender;
float MercSize;
int32 State;
uint32 Stance;
int32 hp;
int32 mana;
int32 endurance;
uint8 face;
uint8 luclinHairStyle;
uint8 luclinHairColor;
uint8 luclinEyeColor;
uint8 luclinEyeColor2;
uint8 luclinBeardColor;
uint8 luclinBeard;
uint32 drakkinHeritage;
uint32 drakkinTattoo;
uint32 drakkinDetails;
};
struct MercSpellEntry {
uint8 proficiencyid;
uint16 spellid; // <= 0 = no spell
uint32 type; // 0 = never, must be one (and only one) of the defined values
int16 stance; // 0 = all, + = only this stance, - = all except this stance
uint8 minlevel;
uint8 maxlevel;
int16 slot;
uint16 proc_chance;
uint32 time_cancast; // when we can cast this spell next
};
struct ClientMercEntry {
uint32 id;
uint32 npcid;
};
class ZoneDatabase : public SharedDatabase {
typedef std::list<ServerLootItem_Struct*> ItemList;
public:
ZoneDatabase();
ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
virtual ~ZoneDatabase();
/* Objects and World Containers */
void LoadWorldContainer(uint32 parentid, ItemInst* container);
void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container);
void DeleteWorldContainer(uint32 parent_id,uint32 zone_id);
uint32 AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst);
void UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst);
void DeleteObject(uint32 id);
Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs);
/* Traders */
void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot);
void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges);
void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice);
void DeleteTraderItem(uint32 char_id);
void DeleteTraderItem(uint32 char_id,uint16 slot_id);
ItemInst* LoadSingleTraderItem(uint32 char_id, int uniqueid);
Trader_Struct* LoadTraderItem(uint32 char_id);
TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id);
/* Buyer/Barter */
void AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char *ItemName, uint32 Quantity, uint32 Price);
void RemoveBuyLine(uint32 CharID, uint32 BuySlot);
void DeleteBuyLines(uint32 CharID);
void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity);
/* General Character Related Stuff */
bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
void SaveBuffs(Client *c);
void LoadBuffs(Client *c);
void LoadPetInfo(Client *c);
void SavePetInfo(Client *c);
void RemoveTempFactions(Client *c);
/* Character Data Loaders */
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Saves */
bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const xyz_heading& position, uint8 is_home);
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Deletes */
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
bool DeleteCharacterLeadershipAAs(uint32 character_id);
bool DeleteCharacterAAs(uint32 character_id);
bool DeleteCharacterDye(uint32 character_id);
/* Character Inventory */
bool NoRentExpired(const char* name);
/* Corpses */
bool DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id);
uint32 GetCharacterCorpseItemCount(uint32 corpse_id);
bool LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs);
Corpse* LoadCharacterCorpse(uint32 player_corpse_id);
Corpse* SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, const xyz_heading& position);
void MarkCorpseAsRezzed(uint32 dbid);
bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes);
bool BuryCharacterCorpse(uint32 dbid);
bool BuryAllCharacterCorpses(uint32 charid);
bool DeleteCharacterCorpse(uint32 dbid);
bool SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, const xyz_heading& position);
bool SummonAllGraveyardCorpses(uint32 cur_zoneid, uint32 dest_zoneid, uint16 dest_instanceid, const xyz_heading& position);
bool UnburyCharacterCorpse(uint32 dbid, uint32 new_zoneid, uint16 dest_instanceid, const xyz_heading& position);
bool LoadCharacterCorpses(uint32 iZoneID, uint16 iInstanceID);
bool DeleteGraveyard(uint32 zone_id, uint32 graveyard_id);
uint32 GetCharacterCorpseDecayTimer(uint32 corpse_db_id);
uint32 GetCharacterBuriedCorpseCount(uint32 char_id);
uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, const xyz_heading& position);
uint32 CreateGraveyardRecord(uint32 graveyard_zoneid, const xyz_heading& position);
uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id);
uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const xyz_heading& position);
uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const xyz_heading& position, bool rezzed = false);
uint32 GetFirstCorpseID(uint32 char_id);
uint32 GetCharacterCorpseCount(uint32 char_id);
uint32 GetCharacterCorpseID(uint32 char_id, uint8 corpse);
uint32 GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid);
uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type);
/* Faction */
bool GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction = 0);
bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id); //needed for factions Dec, 16 2001
bool GetFactionName(int32 faction_id, char* name, uint32 buflen); // needed for factions Dec, 16 2001
bool GetFactionIdsForNPC(uint32 nfl_id, std::list<struct NPCFaction*> *faction_list, int32* primary_faction = 0); // improve faction handling
bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // needed for factions Dec, 16 2001
bool LoadFactionData();
/* AAs */
bool LoadAAEffects();
bool LoadAAEffects2();
bool LoadSwarmSpells();
SendAA_Struct*GetAASkillVars(uint32 skill_id);
uint8 GetTotalAALevels(uint32 skill_id);
uint32 GetSizeAA();
uint32 CountAAs();
void LoadAAs(SendAA_Struct **load);
uint32 CountAAEffects();
void FillAAEffects(SendAA_Struct* aa_struct);
/* Zone related */
bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename);
bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd);
bool LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename, uint32 version);
bool UpdateZoneSafeCoords(const char* zonename, const xyz_location& location);
uint8 GetUseCFGSafeCoords();
int getZoneShutDownDelay(uint32 zoneID, uint32 version);
/* Spawns and Spawn Points */
bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list);
bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list);
bool PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spawn2_list, int16 version, uint32 repopdelay = 0);
Spawn2* LoadSpawn2(LinkedList<Spawn2*> &spawn2_list, uint32 spawn2id, uint32 timeleft);
bool CreateSpawn2(Client *c, uint32 spawngroup, const char* zone, const xyz_heading& position, uint32 respawn, uint32 variance, uint16 condition, int16 cond_value);
void UpdateSpawn2Timeleft(uint32 id, uint16 instance_id,uint32 timeleft);
uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id);
void UpdateSpawn2Status(uint32 id, uint8 new_status);
/* Grids/Paths */
uint32 GetFreeGrid(uint16 zoneid);
void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too, uint16 zoneid);
void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num, uint16 zoneid);
void AddWP(Client *c, uint32 gridid, uint32 wpnum, const xyz_heading& position, uint32 pause, uint16 zoneid);
uint32 AddWPForSpawn(Client *c, uint32 spawn2id, const xyz_heading& position, uint32 pause, int type1, int type2, uint16 zoneid);
void ModifyGrid(Client *c, bool remove, uint32 id, uint8 type = 0, uint8 type2 = 0, uint16 zoneid = 0);
void ModifyWP(Client *c, uint32 grid_id, uint32 wp_num, const xyz_location& location, uint32 script = 0, uint16 zoneid = 0);
uint8 GetGridType(uint32 grid, uint32 zoneid);
uint8 GetGridType2(uint32 grid, uint16 zoneid);
bool GetWaypoints(uint32 grid, uint16 zoneid, uint32 num, wplist* wp);
void AssignGrid(Client *client, const xy_location& location, uint32 id);
int GetHighestGrid(uint32 zoneid);
int GetHighestWaypoint(uint32 zoneid, uint32 gridid);
/* NPCs */
uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete
uint32 CreateNewNPCCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 extra);
uint32 AddNewNPCSpawnGroupCommand(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 respawnTime);
uint32 DeleteSpawnLeaveInNPCTypeTable(const char* zone, Client *client, NPC* spawn);
uint32 DeleteSpawnRemoveFromNPCTypeTable(const char* zone, uint32 zone_version, Client *client, NPC* spawn);
uint32 AddSpawnFromSpawnGroup(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID);
uint32 AddNPCTypes(const char* zone, uint32 zone_version, Client *client, NPC* spawn, uint32 spawnGroupID);
uint32 UpdateNPCTypeAppearance(Client *client, NPC* spawn);
bool SetSpecialAttkFlag(uint8 id, const char* flag);
bool GetPetEntry(const char *pet_type, PetRecord *into);
bool GetPoweredPetEntry(const char *pet_type, int16 petpower, PetRecord *into);
bool GetBasePetItems(int32 equipmentset, uint32 *items);
void AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat);
void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop);
uint32 GetMaxNPCSpellsID();
uint32 GetMaxNPCSpellsEffectsID();
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);
const NPCType* GetNPCType(uint32 id);
/* Mercs */
const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel);
void LoadMercEquipment(Merc *merc);
void SaveMercBuffs(Merc *merc);
void LoadMercBuffs(Merc *merc);
bool LoadMercInfo(Client *c);
bool LoadCurrentMerc(Client *c);
bool SaveMerc(Merc *merc);
bool DeleteMerc(uint32 merc_id);
/* Petitions */
void UpdateBug(BugStruct* bug);
void UpdateBug(PetitionBug_Struct* bug);
void DeletePetitionFromDB(Petition* wpet);
void UpdatePetitionToDB(Petition* wpet);
void InsertPetitionToDB(Petition* wpet);
void RefreshPetitionsFromDB();
/* Merchants */
void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges);
void DeleteMerchantTemp(uint32 npcid, uint32 slot);
/* Tradeskills */
bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec);
uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */
uint32 GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance);
void UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint32 madecount);
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
/* Tribute */
bool LoadTributes();
/* Doors */
bool DoorIsOpen(uint8 door_id,const char* zone_name);
void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name);
bool LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version);
bool CheckGuildDoor(uint8 doorid,uint16 guild_id, const char* zone);
bool SetGuildDoor(uint8 doorid,uint16 guild_id, const char* zone);
uint32 GetGuildEQID(uint32 guilddbid);
void UpdateDoorGuildID(int doorid, int guild_id);
int32 GetDoorsCount(uint32* oMaxID, const char *zone_name, int16 version);
int32 GetDoorsCountPlusOne(const char *zone_name, int16 version);
int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version);
void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, const xyz_heading& position, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize);
/* Blocked Spells */
int32 GetBlockedSpellsCount(uint32 zoneid);
bool LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid);
/* Traps */
bool LoadTraps(const char* zonename, int16 version);
char* GetTrapMessage(uint32 trap_id);
/* Time */
uint32 GetZoneTZ(uint32 zoneid, uint32 version);
bool SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz);
/* Group */
void RefreshGroupFromDB(Client *c);
uint8 GroupCount(uint32 groupid);
/* Raid */
uint8 RaidGroupCount(uint32 raidid, uint32 groupid);
/* Instancing */
void ListAllInstances(Client* c, uint32 charid);
/* QGlobals */
void QGlobalPurge();
/* Alternate Currency */
void LoadAltCurrencyValues(uint32 char_id, std::map<uint32, uint32> &currency);
void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value);
/*
* Misc stuff.
* PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD
* REALLY HAS NO BETTER SECTION
*/
bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid);
void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0);
uint32 GetKarma(uint32 acct_id);
void UpdateKarma(uint32 acct_id, uint32 amount);
/* Things which really dont belong here... */
int16 CommandRequirement(const char* commandname);
protected:
void ZDBInitVars();
uint32 max_faction;
Faction** faction_array;
uint32 npc_spells_maxid;
uint32 npc_spellseffects_maxid;
DBnpcspells_Struct** npc_spells_cache;
bool* npc_spells_loadtried;
DBnpcspellseffects_Struct** npc_spellseffects_cache;
bool* npc_spellseffects_loadtried;
uint8 door_isopen_array[255];
};
extern ZoneDatabase database;
#endif /*ZONEDB_H_*/
+5 -7
View File
@@ -15,17 +15,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "zone.h"
#include "worldserver.h"
#include "masterentity.h"
#include "../common/packet_dump.h"
#include "../common/debug.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "string_ids.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include "zone.h"
extern QueryServ* QServ;
extern WorldServer worldserver;