mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-23 16:48:21 +00:00
Merge from master
This commit is contained in:
@@ -2107,6 +2107,18 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
#endif //BOTS
|
||||
}
|
||||
|
||||
if(give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) {
|
||||
|
||||
if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()){
|
||||
Mob* temp_owner = nullptr;
|
||||
temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner());
|
||||
|
||||
if (temp_owner)
|
||||
give_exp = temp_owner;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PlayerCount = 0; // QueryServ Player Counting
|
||||
|
||||
Client *give_exp_client = nullptr;
|
||||
@@ -3937,6 +3949,11 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DivineAura()) {
|
||||
mlog(COMBAT__PROCS, "Procs canceled, Divine Aura is in effect.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!weapon_g) {
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, on);
|
||||
return;
|
||||
|
||||
+3
-3
@@ -538,9 +538,9 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
}
|
||||
|
||||
void Client::CalcEdibleBonuses(StatBonuses* newbon) {
|
||||
#if EQDEBUG >= 11
|
||||
std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<<std::endl;
|
||||
#endif
|
||||
//#if EQDEBUG >= 11
|
||||
// std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<<std::endl;
|
||||
//#endif
|
||||
// Search player slots for skill=14(food) and skill=15(drink)
|
||||
uint32 i;
|
||||
|
||||
|
||||
+1
-1
@@ -11276,7 +11276,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
if(!results.Success())
|
||||
return;
|
||||
|
||||
int slotmaterial = Inventory::CalcMaterialFromSlot(setslot);
|
||||
uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot);
|
||||
c->GetTarget()->CastToBot()->SendWearChange(slotmaterial);
|
||||
}
|
||||
else {
|
||||
|
||||
+12
-26
@@ -2685,8 +2685,11 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
|
||||
const Item_Struct* item = database.GetItem(item_id);
|
||||
if (item && (item->ItemClass==ItemClassCommon))
|
||||
{
|
||||
uint32 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
m_pp.item_material[matslot] = GetEquipmentMaterial(matslot);
|
||||
uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != _MaterialInvalid)
|
||||
{
|
||||
m_pp.item_material[matslot] = GetEquipmentMaterial(matslot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3016,31 +3019,14 @@ void Client::SetTint(int16 in_slot, uint32 color) {
|
||||
|
||||
// Still need to reconcile bracer01 versus bracer02
|
||||
void Client::SetTint(int16 in_slot, Color_Struct& color) {
|
||||
if (in_slot==MainHead)
|
||||
m_pp.item_tint[MaterialHead].color=color.color;
|
||||
else if (in_slot==MainArms)
|
||||
m_pp.item_tint[MaterialArms].color=color.color;
|
||||
else if (in_slot==MainWrist1)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
/*
|
||||
// non-live behavior
|
||||
else if (in_slot==SLOT_BRACER02)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
*/
|
||||
else if (in_slot==MainHands)
|
||||
m_pp.item_tint[MaterialHands].color=color.color;
|
||||
else if (in_slot==MainPrimary)
|
||||
m_pp.item_tint[MaterialPrimary].color=color.color;
|
||||
else if (in_slot==MainSecondary)
|
||||
m_pp.item_tint[MaterialSecondary].color=color.color;
|
||||
else if (in_slot==MainChest)
|
||||
m_pp.item_tint[MaterialChest].color=color.color;
|
||||
else if (in_slot==MainLegs)
|
||||
m_pp.item_tint[MaterialLegs].color=color.color;
|
||||
else if (in_slot==MainFeet)
|
||||
m_pp.item_tint[MaterialFeet].color=color.color;
|
||||
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
|
||||
uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != _MaterialInvalid)
|
||||
{
|
||||
m_pp.item_tint[matslot].color = color.color;
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Client::SetHideMe(bool flag)
|
||||
|
||||
@@ -1428,8 +1428,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
|
||||
/* Set item material tint */
|
||||
for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++)
|
||||
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
|
||||
m_pp.item_tint[i].rgb.use_tint = 0xFF;
|
||||
{
|
||||
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
|
||||
{
|
||||
m_pp.item_tint[i].rgb.use_tint = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (level){ level = m_pp.level; }
|
||||
|
||||
@@ -5745,7 +5749,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::list<int> pathlist = zone->pathing->FindRoute(Start, End);
|
||||
std::deque<int> pathlist = zone->pathing->FindRoute(Start, End);
|
||||
|
||||
if (pathlist.size() == 0)
|
||||
{
|
||||
@@ -5784,7 +5788,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
||||
p.z = GetZ();
|
||||
points.push_back(p);
|
||||
|
||||
for (std::list<int>::iterator Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
||||
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
||||
{
|
||||
if ((*Iterator) == -1) // Teleporter
|
||||
{
|
||||
|
||||
+1
-1
@@ -2664,7 +2664,7 @@ void EntityList::FindPathsToAllNPCs()
|
||||
while (it != npc_list.end()) {
|
||||
Map::Vertex Node0 = zone->pathing->GetPathNodeCoordinates(0, false);
|
||||
Map::Vertex Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ());
|
||||
std::list<int> Route = zone->pathing->FindRoute(Node0, Dest);
|
||||
std::deque<int> Route = zone->pathing->FindRoute(Node0, Dest);
|
||||
if (Route.size() == 0)
|
||||
printf("Unable to find a route to %s\n", it->second->GetName());
|
||||
else
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ void Mob::CalculateNewFearpoint()
|
||||
|
||||
Map::Vertex CurrentPosition(GetX(), GetY(), GetZ());
|
||||
|
||||
std::list<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
|
||||
std::deque<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
|
||||
|
||||
if(Route.size() > 0)
|
||||
{
|
||||
|
||||
+94
-85
@@ -542,6 +542,8 @@ float Mob::_GetMovementSpeed(int mod) const
|
||||
// http://everquest.allakhazam.com/db/item.html?item=1721;page=1;howmany=50#m10822246245352
|
||||
if (IsRooted())
|
||||
return 0.0f;
|
||||
else if (IsPseudoRooted())
|
||||
return 0.00001f;
|
||||
|
||||
float speed_mod = runspeed;
|
||||
|
||||
@@ -2795,10 +2797,17 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const
|
||||
{
|
||||
const Item_Struct *item;
|
||||
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
if(item != 0)
|
||||
if (armor_tint[material_slot])
|
||||
{
|
||||
return item->Color;
|
||||
return armor_tint[material_slot];
|
||||
}
|
||||
else
|
||||
{
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
if (item != 0)
|
||||
{
|
||||
return item->Color;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5323,98 +5332,98 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot)
|
||||
}
|
||||
|
||||
if (slot < 16){
|
||||
if (id == "classes") {stat = spells[spell_id].classes[slot]; }
|
||||
else if (id == "dieties") {stat = spells[spell_id].deities[slot];}
|
||||
if (id == "classes") {return spells[spell_id].classes[slot]; }
|
||||
else if (id == "dieties") {return spells[spell_id].deities[slot];}
|
||||
}
|
||||
|
||||
if (slot < 12){
|
||||
if (id == "base") {stat = spells[spell_id].base[slot];}
|
||||
else if (id == "base2") {stat = spells[spell_id].base2[slot];}
|
||||
else if (id == "max") {stat = spells[spell_id].max[slot];}
|
||||
else if (id == "formula") {spells[spell_id].formula[slot];}
|
||||
else if (id == "effectid") {spells[spell_id].effectid[slot];}
|
||||
if (id == "base") {return spells[spell_id].base[slot];}
|
||||
else if (id == "base2") {return spells[spell_id].base2[slot];}
|
||||
else if (id == "max") {return spells[spell_id].max[slot];}
|
||||
else if (id == "formula") {return spells[spell_id].formula[slot];}
|
||||
else if (id == "effectid") {return spells[spell_id].effectid[slot];}
|
||||
}
|
||||
|
||||
if (slot < 4){
|
||||
if (id == "components") { spells[spell_id].components[slot];}
|
||||
else if (id == "component_counts") {spells[spell_id].component_counts[slot];}
|
||||
else if (id == "NoexpendReagent") {spells[spell_id].NoexpendReagent[slot];}
|
||||
if (id == "components") { return spells[spell_id].components[slot];}
|
||||
else if (id == "component_counts") { return spells[spell_id].component_counts[slot];}
|
||||
else if (id == "NoexpendReagent") {return spells[spell_id].NoexpendReagent[slot];}
|
||||
}
|
||||
|
||||
if (id == "range") {stat = static_cast<int32>(spells[spell_id].range); }
|
||||
else if (id == "aoerange") {stat = static_cast<int32>(spells[spell_id].aoerange);}
|
||||
else if (id == "pushback") {stat = static_cast<int32>(spells[spell_id].pushback);}
|
||||
else if (id == "pushup") {stat = static_cast<int32>(spells[spell_id].pushup);}
|
||||
else if (id == "cast_time") {stat = spells[spell_id].cast_time;}
|
||||
else if (id == "recovery_time") {stat = spells[spell_id].recovery_time;}
|
||||
else if (id == "recast_time") {stat = spells[spell_id].recast_time;}
|
||||
else if (id == "buffdurationformula") {stat = spells[spell_id].buffdurationformula;}
|
||||
else if (id == "buffduration") {stat = spells[spell_id].buffduration;}
|
||||
else if (id == "AEDuration") {stat = spells[spell_id].AEDuration;}
|
||||
else if (id == "mana") {stat = spells[spell_id].mana;}
|
||||
if (id == "range") {return static_cast<int32>(spells[spell_id].range); }
|
||||
else if (id == "aoerange") {return static_cast<int32>(spells[spell_id].aoerange);}
|
||||
else if (id == "pushback") {return static_cast<int32>(spells[spell_id].pushback);}
|
||||
else if (id == "pushup") {return static_cast<int32>(spells[spell_id].pushup);}
|
||||
else if (id == "cast_time") {return spells[spell_id].cast_time;}
|
||||
else if (id == "recovery_time") {return spells[spell_id].recovery_time;}
|
||||
else if (id == "recast_time") {return spells[spell_id].recast_time;}
|
||||
else if (id == "buffdurationformula") {return spells[spell_id].buffdurationformula;}
|
||||
else if (id == "buffduration") {return spells[spell_id].buffduration;}
|
||||
else if (id == "AEDuration") {return spells[spell_id].AEDuration;}
|
||||
else if (id == "mana") {return spells[spell_id].mana;}
|
||||
//else if (id == "LightType") {stat = spells[spell_id].LightType;} - Not implemented
|
||||
else if (id == "goodEffect") {stat = spells[spell_id].goodEffect;}
|
||||
else if (id == "Activated") {stat = spells[spell_id].Activated;}
|
||||
else if (id == "resisttype") {stat = spells[spell_id].resisttype;}
|
||||
else if (id == "targettype") {stat = spells[spell_id].targettype;}
|
||||
else if (id == "basedeiff") {stat = spells[spell_id].basediff;}
|
||||
else if (id == "skill") {stat = spells[spell_id].skill;}
|
||||
else if (id == "zonetype") {stat = spells[spell_id].zonetype;}
|
||||
else if (id == "EnvironmentType") {stat = spells[spell_id].EnvironmentType;}
|
||||
else if (id == "TimeOfDay") {stat = spells[spell_id].TimeOfDay;}
|
||||
else if (id == "CastingAnim") {stat = spells[spell_id].CastingAnim;}
|
||||
else if (id == "SpellAffectIndex") {stat = spells[spell_id].SpellAffectIndex; }
|
||||
else if (id == "disallow_sit") {stat = spells[spell_id].disallow_sit; }
|
||||
else if (id == "goodEffect") {return spells[spell_id].goodEffect;}
|
||||
else if (id == "Activated") {return spells[spell_id].Activated;}
|
||||
else if (id == "resisttype") {return spells[spell_id].resisttype;}
|
||||
else if (id == "targettype") {return spells[spell_id].targettype;}
|
||||
else if (id == "basedeiff") {return spells[spell_id].basediff;}
|
||||
else if (id == "skill") {return spells[spell_id].skill;}
|
||||
else if (id == "zonetype") {return spells[spell_id].zonetype;}
|
||||
else if (id == "EnvironmentType") {return spells[spell_id].EnvironmentType;}
|
||||
else if (id == "TimeOfDay") {return spells[spell_id].TimeOfDay;}
|
||||
else if (id == "CastingAnim") {return spells[spell_id].CastingAnim;}
|
||||
else if (id == "SpellAffectIndex") {return spells[spell_id].SpellAffectIndex; }
|
||||
else if (id == "disallow_sit") {return spells[spell_id].disallow_sit; }
|
||||
//else if (id == "spellanim") {stat = spells[spell_id].spellanim; } - Not implemented
|
||||
else if (id == "uninterruptable") {stat = spells[spell_id].uninterruptable; }
|
||||
else if (id == "ResistDiff") {stat = spells[spell_id].ResistDiff; }
|
||||
else if (id == "dot_stacking_exemp") {stat = spells[spell_id].dot_stacking_exempt; }
|
||||
else if (id == "RecourseLink") {stat = spells[spell_id].RecourseLink; }
|
||||
else if (id == "no_partial_resist") {stat = spells[spell_id].no_partial_resist; }
|
||||
else if (id == "short_buff_box") {stat = spells[spell_id].short_buff_box; }
|
||||
else if (id == "descnum") {stat = spells[spell_id].descnum; }
|
||||
else if (id == "effectdescnum") {stat = spells[spell_id].effectdescnum; }
|
||||
else if (id == "npc_no_los") {stat = spells[spell_id].npc_no_los; }
|
||||
else if (id == "reflectable") {stat = spells[spell_id].reflectable; }
|
||||
else if (id == "bonushate") {stat = spells[spell_id].bonushate; }
|
||||
else if (id == "EndurCost") {stat = spells[spell_id].EndurCost; }
|
||||
else if (id == "EndurTimerIndex") {stat = spells[spell_id].EndurTimerIndex; }
|
||||
else if (id == "IsDisciplineBuf") {stat = spells[spell_id].IsDisciplineBuff; }
|
||||
else if (id == "HateAdded") {stat = spells[spell_id].HateAdded; }
|
||||
else if (id == "EndurUpkeep") {stat = spells[spell_id].EndurUpkeep; }
|
||||
else if (id == "numhitstype") {stat = spells[spell_id].numhitstype; }
|
||||
else if (id == "numhits") {stat = spells[spell_id].numhits; }
|
||||
else if (id == "pvpresistbase") {stat = spells[spell_id].pvpresistbase; }
|
||||
else if (id == "pvpresistcalc") {stat = spells[spell_id].pvpresistcalc; }
|
||||
else if (id == "pvpresistcap") {stat = spells[spell_id].pvpresistcap; }
|
||||
else if (id == "spell_category") {stat = spells[spell_id].spell_category; }
|
||||
else if (id == "can_mgb") {stat = spells[spell_id].can_mgb; }
|
||||
else if (id == "dispel_flag") {stat = spells[spell_id].dispel_flag; }
|
||||
else if (id == "MinResist") {stat = spells[spell_id].MinResist; }
|
||||
else if (id == "MaxResist") {stat = spells[spell_id].MaxResist; }
|
||||
else if (id == "viral_targets") {stat = spells[spell_id].viral_targets; }
|
||||
else if (id == "viral_timer") {stat = spells[spell_id].viral_timer; }
|
||||
else if (id == "NimbusEffect") {stat = spells[spell_id].NimbusEffect; }
|
||||
else if (id == "directional_start") {stat = static_cast<int32>(spells[spell_id].directional_start); }
|
||||
else if (id == "directional_end") {stat = static_cast<int32>(spells[spell_id].directional_end); }
|
||||
else if (id == "not_extendable") {stat = spells[spell_id].not_extendable; }
|
||||
else if (id == "suspendable") {stat = spells[spell_id].suspendable; }
|
||||
else if (id == "viral_range") {stat = spells[spell_id].viral_range; }
|
||||
else if (id == "spellgroup") {stat = spells[spell_id].spellgroup; }
|
||||
else if (id == "rank") {stat = spells[spell_id].rank; }
|
||||
else if (id == "powerful_flag") {stat = spells[spell_id].powerful_flag; }
|
||||
else if (id == "CastRestriction") {stat = spells[spell_id].CastRestriction; }
|
||||
else if (id == "AllowRest") {stat = spells[spell_id].AllowRest; }
|
||||
else if (id == "InCombat") {stat = spells[spell_id].InCombat; }
|
||||
else if (id == "OutofCombat") {stat = spells[spell_id].OutofCombat; }
|
||||
else if (id == "aemaxtargets") {stat = spells[spell_id].aemaxtargets; }
|
||||
else if (id == "maxtargets") {stat = spells[spell_id].maxtargets; }
|
||||
else if (id == "persistdeath") {stat = spells[spell_id].persistdeath; }
|
||||
else if (id == "min_dist") {stat = static_cast<int32>(spells[spell_id].min_dist); }
|
||||
else if (id == "min_dist_mod") {stat = static_cast<int32>(spells[spell_id].min_dist_mod); }
|
||||
else if (id == "max_dist") {stat = static_cast<int32>(spells[spell_id].max_dist); }
|
||||
else if (id == "min_range") {stat = static_cast<int32>(spells[spell_id].min_range); }
|
||||
else if (id == "DamageShieldType") {stat = spells[spell_id].DamageShieldType; }
|
||||
else if (id == "uninterruptable") {return spells[spell_id].uninterruptable; }
|
||||
else if (id == "ResistDiff") {return spells[spell_id].ResistDiff; }
|
||||
else if (id == "dot_stacking_exemp") {return spells[spell_id].dot_stacking_exempt; }
|
||||
else if (id == "RecourseLink") {return spells[spell_id].RecourseLink; }
|
||||
else if (id == "no_partial_resist") {return spells[spell_id].no_partial_resist; }
|
||||
else if (id == "short_buff_box") {return spells[spell_id].short_buff_box; }
|
||||
else if (id == "descnum") {return spells[spell_id].descnum; }
|
||||
else if (id == "effectdescnum") {return spells[spell_id].effectdescnum; }
|
||||
else if (id == "npc_no_los") {return spells[spell_id].npc_no_los; }
|
||||
else if (id == "reflectable") {return spells[spell_id].reflectable; }
|
||||
else if (id == "bonushate") {return spells[spell_id].bonushate; }
|
||||
else if (id == "EndurCost") {return spells[spell_id].EndurCost; }
|
||||
else if (id == "EndurTimerIndex") {return spells[spell_id].EndurTimerIndex; }
|
||||
else if (id == "IsDisciplineBuf") {return spells[spell_id].IsDisciplineBuff; }
|
||||
else if (id == "HateAdded") {return spells[spell_id].HateAdded; }
|
||||
else if (id == "EndurUpkeep") {return spells[spell_id].EndurUpkeep; }
|
||||
else if (id == "numhitstype") {return spells[spell_id].numhitstype; }
|
||||
else if (id == "numhits") {return spells[spell_id].numhits; }
|
||||
else if (id == "pvpresistbase") {return spells[spell_id].pvpresistbase; }
|
||||
else if (id == "pvpresistcalc") {return spells[spell_id].pvpresistcalc; }
|
||||
else if (id == "pvpresistcap") {return spells[spell_id].pvpresistcap; }
|
||||
else if (id == "spell_category") {return spells[spell_id].spell_category; }
|
||||
else if (id == "can_mgb") {return spells[spell_id].can_mgb; }
|
||||
else if (id == "dispel_flag") {return spells[spell_id].dispel_flag; }
|
||||
else if (id == "MinResist") {return spells[spell_id].MinResist; }
|
||||
else if (id == "MaxResist") {return spells[spell_id].MaxResist; }
|
||||
else if (id == "viral_targets") {return spells[spell_id].viral_targets; }
|
||||
else if (id == "viral_timer") {return spells[spell_id].viral_timer; }
|
||||
else if (id == "NimbusEffect") {return spells[spell_id].NimbusEffect; }
|
||||
else if (id == "directional_start") {return static_cast<int32>(spells[spell_id].directional_start); }
|
||||
else if (id == "directional_end") {return static_cast<int32>(spells[spell_id].directional_end); }
|
||||
else if (id == "not_extendable") {return spells[spell_id].not_extendable; }
|
||||
else if (id == "suspendable") {return spells[spell_id].suspendable; }
|
||||
else if (id == "viral_range") {return spells[spell_id].viral_range; }
|
||||
else if (id == "spellgroup") {return spells[spell_id].spellgroup; }
|
||||
else if (id == "rank") {return spells[spell_id].rank; }
|
||||
else if (id == "powerful_flag") {return spells[spell_id].powerful_flag; }
|
||||
else if (id == "CastRestriction") {return spells[spell_id].CastRestriction; }
|
||||
else if (id == "AllowRest") {return spells[spell_id].AllowRest; }
|
||||
else if (id == "InCombat") {return spells[spell_id].InCombat; }
|
||||
else if (id == "OutofCombat") {return spells[spell_id].OutofCombat; }
|
||||
else if (id == "aemaxtargets") {return spells[spell_id].aemaxtargets; }
|
||||
else if (id == "maxtargets") {return spells[spell_id].maxtargets; }
|
||||
else if (id == "persistdeath") {return spells[spell_id].persistdeath; }
|
||||
else if (id == "min_dist") {return static_cast<int32>(spells[spell_id].min_dist); }
|
||||
else if (id == "min_dist_mod") {return static_cast<int32>(spells[spell_id].min_dist_mod); }
|
||||
else if (id == "max_dist") {return static_cast<int32>(spells[spell_id].max_dist); }
|
||||
else if (id == "min_range") {return static_cast<int32>(spells[spell_id].min_range); }
|
||||
else if (id == "DamageShieldType") {return spells[spell_id].DamageShieldType; }
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1225,7 +1225,7 @@ protected:
|
||||
Map::Vertex PathingLastPosition;
|
||||
int PathingLoopCount;
|
||||
int PathingLastNodeVisited;
|
||||
std::list<int> Route;
|
||||
std::deque<int> Route;
|
||||
LOSType PathingLOSState;
|
||||
Timer *PathingLOSCheckTimer;
|
||||
Timer *PathingRouteUpdateTimerShort;
|
||||
|
||||
+1
-1
@@ -2751,7 +2751,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
|
||||
npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc;
|
||||
npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->range_proc = tmprange_proc;
|
||||
npc_spells_cache[iDBSpellsID]->rproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->rproc_chance = tmprproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->defensive_proc = tmpdefensive_proc;
|
||||
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
|
||||
|
||||
+2
-1
@@ -476,7 +476,7 @@ void NPC::CheckMinMaxLevel(Mob *them)
|
||||
if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level)
|
||||
{
|
||||
material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot);
|
||||
if(material != 0xFF)
|
||||
if (material != _MaterialInvalid)
|
||||
SendWearChange(material);
|
||||
|
||||
cur = itemlist.erase(cur);
|
||||
@@ -1942,6 +1942,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
|
||||
else if(id == "special_attacks") { NPCSpecialAttacks(val.c_str(), 0, 1); return; }
|
||||
else if(id == "special_abilities") { ProcessSpecialAbilities(val.c_str()); return; }
|
||||
else if(id == "attack_speed") { attack_speed = (float)atof(val.c_str()); CalcBonuses(); return; }
|
||||
else if(id == "attack_delay") { attack_delay = atoi(val.c_str()); CalcBonuses(); return; }
|
||||
else if(id == "atk") { ATK = atoi(val.c_str()); return; }
|
||||
else if(id == "accuracy") { accuracy_rating = atoi(val.c_str()); return; }
|
||||
else if(id == "avoidance") { avoidance_rating = atoi(val.c_str()); return; }
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
virtual void RangedAttack(Mob* other);
|
||||
virtual void ThrowingAttack(Mob* other) { }
|
||||
int32 GetNumberOfAttacks() const { return attack_count; }
|
||||
void DoRangedAttackDmg(Mob* other, bool Launch=true, int16 damage_mod=0, int16 chance_mod=0, SkillUseTypes skill=SkillArchery, float speed=4.0f, const char *IDFile = nullptr);
|
||||
|
||||
bool DatabaseCastAccepted(int spell_id);
|
||||
bool IsFactionListAlly(uint32 other_faction);
|
||||
@@ -259,6 +260,7 @@ public:
|
||||
uint32 GetMinDMG() const {return min_dmg;}
|
||||
int16 GetSlowMitigation() const {return slow_mitigation;}
|
||||
float GetAttackSpeed() const {return attack_speed;}
|
||||
uint8 GetAttackDelay() const {return attack_delay;}
|
||||
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
||||
uint16 GetPetSpellID() const {return pet_spell_id;}
|
||||
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
|
||||
|
||||
+20
-22
@@ -205,15 +205,15 @@ Map::Vertex PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ)
|
||||
|
||||
}
|
||||
|
||||
std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
std::deque<int> PathManager::FindRoute(int startID, int endID)
|
||||
{
|
||||
_log(PATHING__DEBUG, "FindRoute from node %i to %i", startID, endID);
|
||||
|
||||
memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount);
|
||||
|
||||
std::list<AStarNode> OpenList, ClosedList;
|
||||
std::deque<AStarNode> OpenList, ClosedList;
|
||||
|
||||
std::list<int>Route;
|
||||
std::deque<int>Route;
|
||||
|
||||
AStarNode AStarEntry, CurrentNode;
|
||||
|
||||
@@ -251,7 +251,7 @@ std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
|
||||
Route.push_back(endID);
|
||||
|
||||
std::list<AStarNode>::iterator RouteIterator;
|
||||
std::deque<AStarNode>::iterator RouteIterator;
|
||||
|
||||
while(CurrentNode.PathNodeID != startID)
|
||||
{
|
||||
@@ -300,7 +300,7 @@ std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
|
||||
bool AlreadyInOpenList = false;
|
||||
|
||||
std::list<AStarNode>::iterator OpenListIterator, InsertionPoint = OpenList.end();
|
||||
std::deque<AStarNode>::iterator OpenListIterator, InsertionPoint = OpenList.end();
|
||||
|
||||
for(OpenListIterator = OpenList.begin(); OpenListIterator != OpenList.end(); ++OpenListIterator)
|
||||
{
|
||||
@@ -350,11 +350,11 @@ bool SortPathNodesByDistance(PathNodeSortStruct n1, PathNodeSortStruct n2)
|
||||
return n1.Distance < n2.Distance;
|
||||
}
|
||||
|
||||
std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
_log(PATHING__DEBUG, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
|
||||
std::list<int> noderoute;
|
||||
std::deque<int> noderoute;
|
||||
|
||||
float CandidateNodeRangeXY = RuleR(Pathing, CandidateNodeRangeXY);
|
||||
|
||||
@@ -365,7 +365,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
//
|
||||
int ClosestPathNodeToStart = -1;
|
||||
|
||||
std::list<PathNodeSortStruct> SortedByDistance;
|
||||
std::deque<PathNodeSortStruct> SortedByDistance;
|
||||
|
||||
PathNodeSortStruct TempNode;
|
||||
|
||||
@@ -382,9 +382,9 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
|
||||
|
||||
@@ -420,9 +420,9 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id);
|
||||
_log(PATHING__DEBUG, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)",
|
||||
@@ -456,7 +456,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
int CulledNodes = 0;
|
||||
|
||||
std::list<int>::iterator First, Second;
|
||||
std::deque<int>::iterator First, Second;
|
||||
|
||||
while((noderoute.size() >= 2) && (CulledNodes < NodesToAttemptToCull))
|
||||
{
|
||||
@@ -487,7 +487,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
int CulledNodes = 0;
|
||||
|
||||
std::list<int>::iterator First, Second;
|
||||
std::deque<int>::iterator First, Second;
|
||||
|
||||
while((noderoute.size() >= 2) && (CulledNodes < NodesToAttemptToCull))
|
||||
{
|
||||
@@ -611,7 +611,7 @@ void PathManager::MeshTest()
|
||||
if(j == i)
|
||||
continue;
|
||||
|
||||
std::list<int> Route = FindRoute(PathNodes[i].id, PathNodes[j].id);
|
||||
std::deque<int> Route = FindRoute(PathNodes[i].id, PathNodes[j].id);
|
||||
|
||||
if(Route.size() == 0)
|
||||
{
|
||||
@@ -638,7 +638,7 @@ void PathManager::SimpleMeshTest()
|
||||
|
||||
for(uint32 j = 1; j < Head.PathNodeCount; ++j)
|
||||
{
|
||||
std::list<int> Route = FindRoute(PathNodes[0].id, PathNodes[j].id);
|
||||
std::deque<int> Route = FindRoute(PathNodes[0].id, PathNodes[j].id);
|
||||
|
||||
if(Route.size() == 0)
|
||||
{
|
||||
@@ -1103,7 +1103,7 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
|
||||
|
||||
int ClosestPathNodeToStart = -1;
|
||||
|
||||
std::list<PathNodeSortStruct> SortedByDistance;
|
||||
std::deque<PathNodeSortStruct> SortedByDistance;
|
||||
|
||||
PathNodeSortStruct TempNode;
|
||||
|
||||
@@ -1120,9 +1120,9 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
|
||||
|
||||
@@ -1262,9 +1262,7 @@ void Mob::PrintRoute()
|
||||
|
||||
printf("Route is : ");
|
||||
|
||||
std::list<int>::iterator Iterator;
|
||||
|
||||
for(Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
|
||||
for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
|
||||
{
|
||||
printf("%i, ", (*Iterator));
|
||||
}
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
class Client;
|
||||
class Mob;
|
||||
@@ -60,8 +60,8 @@ public:
|
||||
static PathManager *LoadPathFile(const char *ZoneName);
|
||||
bool loadPaths(FILE *fp);
|
||||
void PrintPathing();
|
||||
std::list<int> FindRoute(Map::Vertex Start, Map::Vertex End);
|
||||
std::list<int> FindRoute(int startID, int endID);
|
||||
std::deque<int> FindRoute(Map::Vertex Start, Map::Vertex End);
|
||||
std::deque<int> FindRoute(int startID, int endID);
|
||||
|
||||
Map::Vertex GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
|
||||
bool CheckLosFN(Map::Vertex a, Map::Vertex b);
|
||||
|
||||
@@ -2119,6 +2119,32 @@ XS(XS_NPC_GetAttackSpeed)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAttackDelay)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)");
|
||||
{
|
||||
NPC * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetAttackDelay();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAccuracyRating)
|
||||
{
|
||||
@@ -2145,6 +2171,32 @@ XS(XS_NPC_GetAccuracyRating)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAvoidanceRating)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetAvoidanceRating();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetSpawnKillCount)
|
||||
{
|
||||
@@ -2245,6 +2297,81 @@ XS(XS_NPC_GetMerchantProbability) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddMeleeProc);
|
||||
XS(XS_NPC_AddMeleeProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddProcToWeapon(spell_id, true, chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddRangedProc);
|
||||
XS(XS_NPC_AddRangedProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddDefensiveProc(spell_id,chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddDefensiveProc);
|
||||
XS(XS_NPC_AddDefensiveProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddProcToWeapon(spell_id, true, chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@@ -2342,11 +2469,16 @@ XS(boot_NPC)
|
||||
newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$");
|
||||
newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$");
|
||||
newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
+107
-82
@@ -103,6 +103,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if (!who)
|
||||
return;
|
||||
|
||||
if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE))
|
||||
return; //-5?
|
||||
|
||||
int32 hate = max_damage;
|
||||
if(hate_override > -1)
|
||||
hate = hate_override;
|
||||
@@ -1059,8 +1062,8 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes
|
||||
|
||||
if(item)
|
||||
SendItemAnimation(other, item, skillInUse, speed);
|
||||
else if (IsNPC())
|
||||
ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse);
|
||||
//else if (IsNPC())
|
||||
//ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1097,12 +1100,19 @@ void Mob::ProjectileAttack()
|
||||
if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){
|
||||
|
||||
if (target){
|
||||
if (ProjectileAtk[i].skill == SkillArchery)
|
||||
DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillThrowing)
|
||||
DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg))
|
||||
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
|
||||
|
||||
if (IsNPC())
|
||||
CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast<SkillUseTypes>(ProjectileAtk[i].skill));
|
||||
|
||||
else
|
||||
{
|
||||
if (ProjectileAtk[i].skill == SkillArchery)
|
||||
DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillThrowing)
|
||||
DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg))
|
||||
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectileAtk[i].increment = 0;
|
||||
@@ -1187,14 +1197,8 @@ void NPC::RangedAttack(Mob* other)
|
||||
attacks = attacks > 0 ? attacks : 1;
|
||||
for(int i = 0; i < attacks; ++i) {
|
||||
|
||||
//if we have SPECATK_RANGED_ATK set then we range attack without weapon or ammo
|
||||
const Item_Struct* weapon = nullptr;
|
||||
const Item_Struct* ammo = nullptr;
|
||||
if(!GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||
{
|
||||
//find our bow and ammo return if we can't find them...
|
||||
return;
|
||||
}
|
||||
|
||||
int sa_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); //Min Range of NPC attack
|
||||
int sa_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); //Max Range of NPC attack
|
||||
@@ -1208,16 +1212,11 @@ void NPC::RangedAttack(Mob* other)
|
||||
if (sa_min_range)
|
||||
min_range = static_cast<float>(sa_min_range);
|
||||
|
||||
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", max_range);
|
||||
max_range *= max_range;
|
||||
if(DistNoRootNoZ(*other) > max_range) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack out of range...%.2f vs %.2f", DistNoRootNoZ(*other), max_range);
|
||||
//target is out of range, client does a message
|
||||
if(DistNoRoot(*other) > max_range)
|
||||
return;
|
||||
}
|
||||
else if(DistNoRootNoZ(*other) < (min_range * min_range))
|
||||
else if(DistNoRoot(*other) < (min_range * min_range))
|
||||
return;
|
||||
|
||||
|
||||
if(!other || !IsAttackAllowed(other) ||
|
||||
IsCasting() ||
|
||||
@@ -1229,74 +1228,100 @@ void NPC::RangedAttack(Mob* other)
|
||||
return;
|
||||
}
|
||||
|
||||
SkillUseTypes skillinuse = SkillArchery;
|
||||
skillinuse = static_cast<SkillUseTypes>(GetRangedSkill());
|
||||
|
||||
if(!ammo && !GetAmmoIDfile())
|
||||
ammo = database.GetItem(8005);
|
||||
|
||||
if(ammo)
|
||||
SendItemAnimation(other, ammo, SkillArchery);
|
||||
else
|
||||
ProjectileAnimation(other, 0,false,0,0,0,0,GetAmmoIDfile(),skillinuse);
|
||||
|
||||
FaceTarget(other);
|
||||
|
||||
if (!other->CheckHitChance(this, skillinuse, MainRange, GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2)))
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, skillinuse);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16 WDmg = GetWeaponDamage(other, weapon);
|
||||
int16 ADmg = GetWeaponDamage(other, ammo);
|
||||
int32 TotalDmg = 0;
|
||||
if(WDmg > 0 || ADmg > 0)
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName());
|
||||
|
||||
int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||
int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier);
|
||||
|
||||
if(RuleB(Combat, UseIntervalAC))
|
||||
TotalDmg = MaxDmg;
|
||||
else
|
||||
TotalDmg = zone->random.Int(MinDmg, MaxDmg);
|
||||
|
||||
TotalDmg += TotalDmg * GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3) / 100; //Damage modifier
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
other->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
if (TotalDmg > 0)
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, skillinuse);
|
||||
}
|
||||
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
if (TotalDmg > 0)
|
||||
other->AddToHateList(this, TotalDmg, 0, false);
|
||||
else
|
||||
other->AddToHateList(this, 0, 0, false);
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, true, MainRange);
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, false, MainRange);
|
||||
DoRangedAttackDmg(other);
|
||||
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
}
|
||||
|
||||
void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, SkillUseTypes skill, float speed, const char *IDFile) {
|
||||
|
||||
if ((other == nullptr ||
|
||||
(other->HasDied())) ||
|
||||
HasDied() ||
|
||||
(!IsAttackAllowed(other)) ||
|
||||
(other->GetInvul() ||
|
||||
other->GetSpecialAbility(IMMUNE_MELEE)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SkillUseTypes skillInUse = static_cast<SkillUseTypes>(GetRangedSkill());
|
||||
|
||||
if (skill != skillInUse)
|
||||
skillInUse = skill;
|
||||
|
||||
if (Launch)
|
||||
{
|
||||
const char *ammo = "IT10";
|
||||
|
||||
if (IDFile != nullptr)
|
||||
ammo = IDFile;
|
||||
else if (GetAmmoIDfile())
|
||||
ammo = GetAmmoIDfile();
|
||||
|
||||
ProjectileAnimation(other, 0,false,speed,0,0,0,ammo,skillInUse);
|
||||
|
||||
if (RuleB(Combat, ProjectileDmgOnImpact))
|
||||
{
|
||||
TryProjectileAttack(other, nullptr, skillInUse, damage_mod, nullptr, nullptr, 0, speed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chance_mod)
|
||||
chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2);
|
||||
|
||||
if (!other->CheckHitChance(this, skillInUse, MainRange, chance_mod))
|
||||
{
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, skillInUse);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 TotalDmg = 0;
|
||||
int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||
int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier);
|
||||
|
||||
if(RuleB(Combat, UseIntervalAC))
|
||||
TotalDmg = MaxDmg;
|
||||
else
|
||||
TotalDmg = zone->random.Int(MinDmg, MaxDmg);
|
||||
|
||||
|
||||
if (!damage_mod)
|
||||
damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier
|
||||
|
||||
TotalDmg += TotalDmg * damage_mod / 100;
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
other->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
|
||||
if (TotalDmg > 0)
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, skillInUse);
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
if (TotalDmg > 0)
|
||||
other->AddToHateList(this, TotalDmg, 0, false);
|
||||
else
|
||||
other->AddToHateList(this, 0, 0, false);
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied())
|
||||
TrySkillProc(other, skillInUse, 0, true, MainRange);
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
TrySkillProc(other, skillInUse, 0, false, MainRange);
|
||||
}
|
||||
|
||||
uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) {
|
||||
uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(SkillThrowing)) / 100);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user