Merge branch 'master' into inv2

This commit is contained in:
KimLS
2015-03-25 15:55:16 -07:00
19 changed files with 536 additions and 86 deletions
+3 -2
View File
@@ -3650,6 +3650,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
(frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) &&
!attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
Log.Out(Logs::Detail, Logs::Combat, "Frontal stun resisted. %d chance.", frontal_stun_resist);
} else {
// Normal stun resist check.
if (stun_resist && zone->random.Roll(stun_resist)) {
@@ -3994,7 +3995,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const ItemData *weapon, Mob *on, u
// We can proc once here, either weapon or one aug
bool proced = false; // silly bool to prevent augs from going if weapon does
skillinuse = GetSkillByItemType(weapon->ItemType);
if (weapon->Proc.Type == ET_CombatProc) {
if (weapon->Proc.Type == ET_CombatProc && IsValidSpell(weapon->Proc.Effect)) {
float WPC = ProcChance * (100.0f + // Proc chance for this weapon
static_cast<float>(weapon->ProcRate)) / 100.0f;
if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really.
@@ -4032,7 +4033,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const ItemData *weapon, Mob *on, u
if (!aug)
continue;
if (aug->Proc.Type == ET_CombatProc) {
if (aug->Proc.Type == ET_CombatProc && IsValidSpell(aug->Proc.Effect)) {
float APC = ProcChance * (100.0f + // Proc chance for this aug
static_cast<float>(aug->ProcRate)) / 100.0f;
if (zone->random.Roll(APC)) {
+1 -1
View File
@@ -1291,7 +1291,7 @@ protected:
bool client_data_loaded;
int16 GetFocusEffect(focusType type, uint16 spell_id);
int16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
Mob* bind_sight_target;
+5 -1
View File
@@ -2607,7 +2607,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app)
++iter;
}
if (item_id == 0) {
if (item_id == 0 || reclaim->count == 0) {
return;
}
@@ -13319,6 +13319,10 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app)
if (database.GetItem(gis->Items[i])) {
database.SaveTraderItem(this->CharacterID(), gis->Items[i], gis->SerialNumber[i],
gis->Charges[i], ints->ItemCost[i], i);
auto inst = FindTraderItemBySerialNumber(gis->SerialNumber[i]);
if(inst)
inst->SetPrice(ints->ItemCost[i]);
}
else {
//return; //sony doesnt memset so assume done on first bad item
+11
View File
@@ -3429,6 +3429,16 @@ XS(XS__clear_npctype_cache)
XSRETURN_EMPTY;
}
XS(XS__reloadzonestaticdata);
XS(XS__reloadzonestaticdata)
{
dXSARGS;
quest_manager.ReloadZoneStaticData();
XSRETURN_EMPTY;
}
XS(XS__qs_send_query);
XS(XS__qs_send_query)
{
@@ -3686,6 +3696,7 @@ EXTERN_C XS(boot_quest)
newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file);
newXS(strcpy(buf, "rain"), XS__rain, file);
newXS(strcpy(buf, "rebind"), XS__rebind, file);
newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file);
newXS(strcpy(buf, "removetitle"), XS__removetitle, file);
newXS(strcpy(buf, "repopzone"), XS__repopzone, file);
newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file);
+5
View File
@@ -1242,6 +1242,10 @@ void lua_clear_npctype_cache(int npctype_id) {
quest_manager.ClearNPCTypeCache(npctype_id);
}
void lua_reloadzonestaticdata() {
quest_manager.ReloadZoneStaticData();
}
double lua_clock() {
timeval read_time;
gettimeofday(&read_time, nullptr);
@@ -1592,6 +1596,7 @@ luabind::scope lua_register_general() {
luabind::def("enable_recipe", &lua_enable_recipe),
luabind::def("disable_recipe", &lua_disable_recipe),
luabind::def("clear_npctype_cache", &lua_clear_npctype_cache),
luabind::def("reloadzonestaticdata", &lua_reloadzonestaticdata),
luabind::def("clock", &lua_clock),
luabind::def("create_npc", &lua_create_npc),
luabind::def("debug", (void(*)(std::string))&lua_debug),
+29 -24
View File
@@ -3616,36 +3616,41 @@ bool Mob::TryFadeEffect(int slot)
void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
{
if(target == nullptr || !IsValidSpell(spell_id))
if(target == nullptr || !IsValidSpell(spell_id) || !IsClient())
return;
int focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id);
uint16 focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id);
if(IsValidSpell(focus_spell)){
int focus_trigger = spells[focus_spell].base2[0];
// For beneficial spells, if the triggered spell is also beneficial then proc it on the target
// if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items)
if(IsBeneficialSpell(spell_id))
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, target);
if(!IsValidSpell(focus_spell))
return;
else
SpellFinished(focus_trigger, this, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
// For detrimental spells, if the triggered spell is beneficial, then it will land on the caster
// if the triggered spell is also detrimental, then it will land on the target
else
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, this);
uint16 focus_trigger = GetSympatheticSpellProcID(focus_spell);
else
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
if(!IsValidSpell(focus_trigger))
return;
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
}
// For beneficial spells, if the triggered spell is also beneficial then proc it on the target
// if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items)
if(IsBeneficialSpell(spell_id))
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, target);
else
SpellFinished(focus_trigger, this, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
// For detrimental spells, if the triggered spell is beneficial, then it will land on the caster
// if the triggered spell is also detrimental, then it will land on the target
else
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, this);
else
SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff);
}
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
}
int32 Mob::GetItemStat(uint32 itemid, const char *identifier)
+2
View File
@@ -1067,6 +1067,8 @@ protected:
void PrintRoute();
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
int16 GetSympatheticSpellProcRate(uint16 spell_id);
uint16 GetSympatheticSpellProcID(uint16 spell_id);
enum {MAX_PROCS = 4};
tProc PermaProcs[MAX_PROCS];
+1 -3
View File
@@ -1839,7 +1839,7 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
if(swarmOwner->IsClient())
{
SetPetOwnerClient(true); //Simple flag to determine if pet belongs to a client
SetAllowBeneficial(1);//Allow temp pets to receive buffs and heals if owner is client.
SetAllowBeneficial(true);//Allow temp pets to receive buffs and heals if owner is client.
//This will allow CLIENT swarm pets NOT to be targeted with F8.
ns->spawn.targetable_with_hotkey = 0;
no_target_hotkey = 1;
@@ -2258,8 +2258,6 @@ bool NPC::CanTalk()
0,0,420,0,0,0,0,425,0,0,0,0,0,0,0,433,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,458,0,0,0,0,0,0,0,0,467,0,0,470,0,0,473};
int talk_check = TalkRace[GetRace() - 1];
if (TalkRace[GetRace() - 1] > 0)
return true;
+5
View File
@@ -1478,6 +1478,11 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques
{
for(uint32 i = 0; i < Head.PathNodeCount; ++i)
{
if(PathNodes[i].id - new_id > 1) {
new_id = PathNodes[i].id - 1;
break;
}
if(PathNodes[i].id > new_id)
new_id = PathNodes[i].id;
}
+27
View File
@@ -2530,6 +2530,32 @@ XS(XS_NPC_ClearLastName)
XSRETURN_EMPTY;
}
XS(XS_NPC_GetCombatState); /* prototype to pass -Wmissing-prototypes */
XS(XS_NPC_GetCombatState)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: NPC::GetCombatState(THIS)");
{
NPC * THIS;
bool RETVAL;
if (sv_derived_from(ST(0), "NPC")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(NPC *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type NPC");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetCombatEvent();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
#ifdef __cplusplus
extern "C"
#endif
@@ -2643,6 +2669,7 @@ XS(boot_NPC)
newXSproto(strcpy(buf, "RemoveDefensiveProc"), XS_NPC_RemoveDefensiveProc, file, "$$");
newXSproto(strcpy(buf, "ChangeLastName"), XS_NPC_ChangeLastName, file, "$:$");
newXSproto(strcpy(buf, "ClearLastName"), XS_NPC_ClearLastName, file, "$");
newXSproto(strcpy(buf, "GetCombatState"), XS_NPC_GetCombatState, file, "$");
XSRETURN_YES;
}
+7
View File
@@ -2927,6 +2927,13 @@ void QuestManager::ClearNPCTypeCache(int npctype_id) {
}
}
void QuestManager::ReloadZoneStaticData()
{
if (zone) {
zone->ReloadStaticData();
}
}
Client *QuestManager::GetInitiator() const {
if(!quests_running_.empty()) {
running_quest e = quests_running_.top();
+1
View File
@@ -249,6 +249,7 @@ public:
bool EnableRecipe(uint32 recipe_id);
bool DisableRecipe(uint32 recipe_id);
void ClearNPCTypeCache(int npctype_id);
void ReloadZoneStaticData();
Client *GetInitiator() const;
NPC *GetNPC() const;
+27 -8
View File
@@ -5177,13 +5177,12 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
return(value*lvlModifier/100);
}
int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
if (IsBardSong(spell_id))
return 0;
uint16 proc_spellid = 0;
uint8 MAX_SYMPATHETIC = 10;
float ProcChance = 0.0f;
std::vector<int> SympatheticProcList;
@@ -5195,7 +5194,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++)
{
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
continue;
TempItem = nullptr;
@@ -5215,7 +5214,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y)
{
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
continue;
ItemInst *aug = nullptr;
@@ -5243,18 +5242,18 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
int buff_max = GetMaxTotalSlots();
for (buff_slot = 0; buff_slot < buff_max; buff_slot++) {
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
continue;
focusspellid = buffs[buff_slot].spellid;
if (IsValidSpell(focusspellid))
if (!IsValidSpell(focusspellid))
continue;
proc_spellid = CalcFocusEffect(type, focusspellid, spell_id);
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]);
ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(spell_id));
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
@@ -5275,7 +5274,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
if (aa_AA < 1 || aa_value < 1)
continue;
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
continue;
proc_spellid = CalcAAFocus(type, aa_AA, spell_id);
@@ -5930,6 +5929,26 @@ float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 I
return ProcChance;
}
int16 Mob::GetSympatheticSpellProcRate(uint16 spell_id)
{
for (int i = 0; i < EFFECT_COUNT; i++){
if (spells[spell_id].effectid[i] == SE_SympatheticProc)
return spells[spell_id].base[i];
}
return 0;
}
uint16 Mob::GetSympatheticSpellProcID(uint16 spell_id)
{
for (int i = 0; i < EFFECT_COUNT; i++){
if (spells[spell_id].effectid[i] == SE_SympatheticProc)
return spells[spell_id].base2[i];
}
return 0;
}
bool Mob::DoHPToManaCovert(uint16 mana_cost)
{
if (spellbonuses.HPToManaConvert){
+1 -1
View File
@@ -2151,7 +2151,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
// it can affect up to 7 people if the targeted group is not our own
// Allow pets who cast group spells to affect the group.
if (spell_target->IsPetOwnerClient()){
if (spell_target->IsPetOwnerClient() && IsPetOwnerClient()){
Mob* owner = spell_target->GetOwner();
if (owner)
+8 -1
View File
@@ -1583,6 +1583,8 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic
return;
}
tbs->Price = BuyItem->GetPrice();
Log.Out(Logs::Detail, Logs::Trading, "Buyitem: Name: %s, IsStackable: %i, Requested Quantity: %i, Charges on Item %i",
BuyItem->GetItem()->Name, BuyItem->IsStackable(), tbs->Quantity, BuyItem->GetCharges());
// If the item is not stackable, then we can only be buying one of them.
@@ -1650,7 +1652,12 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic
outtbs->Price = TotalCost;
}
this->TakeMoneyFromPP(TotalCost);
if(!TakeMoneyFromPP(TotalCost)) {
database.SetHackerFlag(account_name, name, "Attempted to buy something in bazaar but did not have enough money.");
TradeRequestFailed(app);
safe_delete(outapp);
return;
}
Log.Out(Logs::Detail, Logs::Trading, "Customer Paid: %d in Copper", TotalCost);