Multiple combat / functionality updates
Fix #277 - hp / power regen rewrite Also added power_regen_override and hp_regen_override, when set to 1, you can LUA manually set hp_regen and power_regen to enforce it in code RULE R_Spawn, ClassicRegen added. Set to 1 means we do not have both regens when out of combat (eg. out of combat = out of combat regen + in combat regen). In classic you only received in combat or out of combat regen individually. Fix #278 - HatedBy now properly handled, we know when a player/spawn is being hated by other targets Fix #275 - Parry/Riposte, Block and Dodge implemented. Missing Block formula which will become its own issue. Entity GetInfoStruct/SetInfoStruct, cur_avoidance, parry, parry_base, deflection, block are now floats. Added sint16 power_regen adn hp_regen, lastly power_regen_override and hp_regen_override are int8's. Fix #274 - Implemented stats Crushing, Defense, Deflection, Disruption, Fishing, Focus, Foresting, Gathering, Mining, Parry, Piercing, Safe Fall, Slashing and Trapping /waypoint command now allows flushing waypoint if you do not have active target /spawn details [x] supports behind, infront and flank /craftitem added per EmemJr update INSERT INTO commands SET TYPE=1,command='craftitem',subcommand='',HANDLER=526,required_status=100; Crash fix for /add_aa hitting bad spell id LUA Functions: RemoveSpawnSpellBonus(spawn) - used in LUASpell script GetSpell(spell_id, tier, custom_lua_script) - third argument added to setup custom script file AddIconValue(spawn, value) RemoveIconValue(spawn, value) Fix #169 - evac now works correctly, no ghost spawn of self and you can go into combat and see damage taken/given. Also simplified the player spawn / index map (had duplicates unneeded) Fixed region_map_v1 throwing errors on special variable for signed vs unsigned
This commit is contained in:
parent
b344a3f894
commit
6f92367102
29 changed files with 973 additions and 238 deletions
EQ2/source/WorldServer
|
@ -687,9 +687,6 @@ void Bot::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
GetInfoStruct()->set_magic_base((int16)(new_level*1.5 + 10));
|
||||
GetInfoStruct()->set_divine_base((int16)(new_level*1.5 + 10));
|
||||
GetInfoStruct()->set_poison_base((int16)(new_level*1.5 + 10));
|
||||
|
||||
SetHPRegen((int)(new_level*.75) + (int)(new_level / 10) + 3);
|
||||
SetPowerRegen(new_level + (int)(new_level / 10) + 4);
|
||||
/*UpdateTimeStampFlag(LEVEL_UPDATE_FLAG);
|
||||
GetPlayer()->SetCharSheetChanged(true);
|
||||
|
||||
|
|
|
@ -582,7 +582,9 @@ bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string
|
|||
if (heal_amt > 0){
|
||||
//int32 base_roll = heal_amt;
|
||||
//potency mod
|
||||
MStats.lock();
|
||||
heal_amt *= (stats[ITEM_STAT_POTENCY] / 100 + 1);
|
||||
MStats.unlock();
|
||||
|
||||
//primary stat mod, insert forula here when done
|
||||
//heal_amt += base_roll * (GetPrimaryStat()
|
||||
|
@ -682,12 +684,14 @@ bool Entity::SpellHeal(Spawn* target, float distance, LuaSpell* luaspell, string
|
|||
if (target->IsEntity()) {
|
||||
int32 hate_amt = heal_amt / 2;
|
||||
set<int32>::iterator itr;
|
||||
((Entity*)target)->MHatedBy.lock();
|
||||
for (itr = ((Entity*)target)->HatedBy.begin(); itr != ((Entity*)target)->HatedBy.end(); itr++) {
|
||||
Spawn* spawn = GetZone()->GetSpawnByID(*itr);
|
||||
if (spawn && spawn->IsEntity()) {
|
||||
((Entity*)spawn)->AddHate(this, hate_amt);
|
||||
}
|
||||
}
|
||||
((Entity*)target)->MHatedBy.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -702,14 +706,28 @@ int8 Entity::DetermineHit(Spawn* victim, int8 damage_type, float ToHitBonus, boo
|
|||
return DAMAGE_PACKET_RESULT_INVULNERABLE;
|
||||
}
|
||||
|
||||
if(!victim->IsEntity() || (!spell && BehindTarget(victim))) {
|
||||
bool behind = false;
|
||||
if(!victim->IsEntity() || (!spell && victim->GetAdventureClass() != BRAWLER && (behind = BehindTarget(victim)))) {
|
||||
return DAMAGE_PACKET_RESULT_SUCCESSFUL;
|
||||
}
|
||||
|
||||
float bonus = ToHitBonus;
|
||||
Skill* skill = GetSkillByWeaponType(damage_type, true);
|
||||
|
||||
float skillAddedByWeapon = 0.0f;
|
||||
if(skill)
|
||||
{
|
||||
int16 skillID = master_item_list.GetItemStatIDByName(skill->name.data);
|
||||
if(skillID != 0xFFFFFFFF)
|
||||
{
|
||||
MStats.lock();
|
||||
skillAddedByWeapon = stats[skillID];
|
||||
MStats.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (skill)
|
||||
bonus += skill->current_val / 25;
|
||||
bonus += (skill->current_val+skillAddedByWeapon) / 25;
|
||||
if (victim->IsEntity())
|
||||
bonus -= ((Entity*)victim)->GetDamageTypeResistPercentage(damage_type);
|
||||
|
||||
|
@ -725,38 +743,76 @@ int8 Entity::DetermineHit(Spawn* victim, int8 damage_type, float ToHitBonus, boo
|
|||
if(skill)
|
||||
roll_chance -= skill->current_val / 25;
|
||||
|
||||
skill = entity_victim->GetSkillByName("Defense", true);
|
||||
if (skill)
|
||||
chance -= skill->current_val / 25;
|
||||
|
||||
if(rand()%roll_chance >= (chance - entity_victim->GetAgi()/50)){
|
||||
entity_victim->CheckProcs(PROC_TYPE_EVADE, this);
|
||||
return DAMAGE_PACKET_RESULT_DODGE;//successfully dodged
|
||||
}
|
||||
if(rand() % roll_chance >= chance)
|
||||
return DAMAGE_PACKET_RESULT_MISS; //successfully avoided
|
||||
|
||||
if(entity_victim->IsImmune(IMMUNITY_TYPE_RIPOSTE))
|
||||
return DAMAGE_PACKET_RESULT_RIPOSTE;
|
||||
|
||||
// Avoidance Instructions: https://forums.daybreakgames.com/eq2/index.php?threads/avoidance-faq.482979/
|
||||
|
||||
/*Parry: reads as parry in the avoidance tooltip, increased by items with +parry on them
|
||||
Caps at 70%. For plate tanks, works in the front quadrant only, for brawlers this is 360 degrees.
|
||||
A small % of parries will be ripostes, which not only avoid the attack but also damage your attacker
|
||||
*/
|
||||
|
||||
skill = entity_victim->GetSkillByName("Parry", true);
|
||||
if(skill){
|
||||
if(rand()%roll_chance >= (chance - 5 - skill->current_val/25)){ //successful parry
|
||||
if(rand()%100 <= 20) {
|
||||
entity_victim->CheckProcs(PROC_TYPE_RIPOSTE, this);
|
||||
return DAMAGE_PACKET_RESULT_RIPOSTE;
|
||||
float parryChance = entity_victim->GetInfoStruct()->get_parry();
|
||||
float chanceValue = (100.0f - parryChance);
|
||||
|
||||
if(rand()%roll_chance >= chanceValue){ //successful parry
|
||||
/* You may only riposte things in the front quadrant.
|
||||
Riposte is based off of parry: a certain % of parries turn into ripostes.
|
||||
*/
|
||||
if(!behind && victim->InFrontSpawn((Spawn*)this, victim->GetX(), victim->GetZ())) { // if the attacker is not behind the victim, and the victim is facing the attacker (in front of spawn) then we can riposte
|
||||
float riposteChanceValue = parryChance / 7.0f; // Riposte is based off of parry: a certain % of parries turn into ripostes. Unknown what the value is divided by, 7 to make it 10% even.
|
||||
if(rand()%100 <= riposteChanceValue) {
|
||||
entity_victim->CheckProcs(PROC_TYPE_RIPOSTE, this);
|
||||
return DAMAGE_PACKET_RESULT_RIPOSTE;
|
||||
}
|
||||
}
|
||||
entity_victim->CheckProcs(PROC_TYPE_PARRY, this);
|
||||
return DAMAGE_PACKET_RESULT_PARRY;
|
||||
}
|
||||
}
|
||||
|
||||
skill = entity_victim->GetSkillByName("Deflection", true);
|
||||
if(skill){
|
||||
if(rand()%100 >= (chance - skill->current_val/25)) { //successfully deflected
|
||||
return DAMAGE_PACKET_RESULT_DEFLECT;
|
||||
skill = nullptr;
|
||||
|
||||
|
||||
float blockChance = 0.0f;
|
||||
if(victim->GetAdventureClass() == BRAWLER)
|
||||
skill = entity_victim->GetSkillByName("Deflection", true);
|
||||
|
||||
blockChance = entity_victim->GetInfoStruct()->get_block();
|
||||
|
||||
if(blockChance > 0.0f)
|
||||
{
|
||||
blockChance += (blockChance*(entity_victim->GetInfoStruct()->get_block_chance()/100.0f));
|
||||
float chanceValue = (100.0f - blockChance);
|
||||
/* Non-brawlers may only block things in the front quadrant.
|
||||
Riposte is based off of parry: a certain % of parries turn into ripostes.
|
||||
*/
|
||||
float rnd = rand()%roll_chance;
|
||||
if(rnd >= chanceValue){ //successful block
|
||||
if(victim->GetAdventureClass() == BRAWLER || (!behind && victim->InFrontSpawn((Spawn*)this, victim->GetX(), victim->GetZ()))) { // if the attacker is not behind the victim, and the victim is facing the attacker (in front of spawn) then we can block
|
||||
entity_victim->CheckProcs(PROC_TYPE_BLOCK, this);
|
||||
return (victim->GetAdventureClass() == BRAWLER) ? DAMAGE_PACKET_RESULT_DEFLECT : DAMAGE_PACKET_RESULT_BLOCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skill = entity_victim->GetSkillByName("Defense", true);
|
||||
|
||||
float dodgeChance = entity_victim->GetInfoStruct()->get_avoidance_base();
|
||||
if(dodgeChance > 0.0f)
|
||||
{
|
||||
float chanceValue = (100.0f - dodgeChance);
|
||||
float rnd = rand()%roll_chance;
|
||||
if(rnd >= chanceValue){ //successful dodge
|
||||
entity_victim->CheckProcs(PROC_TYPE_EVADE, this);
|
||||
return DAMAGE_PACKET_RESULT_DODGE;//successfully dodged
|
||||
}
|
||||
}
|
||||
if(rand() % roll_chance >= chance)
|
||||
return DAMAGE_PACKET_RESULT_MISS; //successfully avoided
|
||||
}
|
||||
else{
|
||||
skill = entity_victim->GetSkillByName("Spell Avoidance", true);
|
||||
|
@ -873,7 +929,9 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
|||
//Potency and ability mod is only applied to spells/CAs
|
||||
else {
|
||||
// Potency mod
|
||||
MStats.lock();
|
||||
damage *= ((stats[ITEM_STAT_POTENCY] / 100) + 1);
|
||||
MStats.unlock();
|
||||
|
||||
// Ability mod can only give up to half of damage after potency
|
||||
int32 mod = (int32)min(info_struct.get_ability_modifier(), (float)(damage / 2));
|
||||
|
@ -888,7 +946,9 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
|||
|
||||
// Crit Roll
|
||||
else {
|
||||
victim->MStats.lock();
|
||||
float chance = max((float)0, (info_struct.get_crit_chance() - victim->stats[ITEM_STAT_CRITAVOIDANCE]));
|
||||
victim->MStats.unlock();
|
||||
if (MakeRandomFloat(0, 100) <= chance)
|
||||
crit = true;
|
||||
}
|
||||
|
@ -1052,8 +1112,14 @@ bool Entity::CheckInterruptSpell(Entity* attacker) {
|
|||
//modified to 50% and added global rule, 30% was too small at starting levels
|
||||
int8 percent = rule_manager.GetGlobalRule(R_Spells, NoInterruptBaseChance)->GetInt32();
|
||||
Skill* skill = GetSkillByName("Focus", true);
|
||||
|
||||
float focusSkillPts = 0.0f;
|
||||
MStats.lock();
|
||||
focusSkillPts = stats[ITEM_STAT_FOCUS];
|
||||
MStats.unlock();
|
||||
|
||||
if(skill)
|
||||
percent += ((skill->current_val + 1)/6);
|
||||
percent += ((skill->current_val + 1 + focusSkillPts)/6);
|
||||
if(MakeRandomInt(1, 100) > percent) {
|
||||
LogWrite(COMBAT__DEBUG, 0, "Combat", "'%s' interrupted spell for '%s': %i%%", attacker->GetName(), GetName(), percent);
|
||||
GetZone()->Interrupted(this, attacker, SPELL_ERROR_INTERRUPTED);
|
||||
|
|
|
@ -318,7 +318,7 @@ bool Commands::SetSpawnCommand(Client* client, Spawn* target, int8 type, const c
|
|||
}
|
||||
case SPAWN_SET_VALUE_FACIAL_HAIR_TYPE:{
|
||||
if(target->IsEntity()){
|
||||
sprintf(tmp, "%i", ((Entity*)target)->GetHairType());
|
||||
sprintf(tmp, "%i", ((Entity*)target)->GetFacialHairType());
|
||||
((Entity*)target)->SetFacialHairType(val, send_update);
|
||||
}
|
||||
break;
|
||||
|
@ -1638,6 +1638,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
}
|
||||
case COMMAND_WAYPOINT: {
|
||||
bool success = false;
|
||||
client->ClearWaypoint();
|
||||
if (sep && sep->IsNumber(0) && sep->IsNumber(1) && sep->IsNumber(2)) {
|
||||
if (!client->ShowPathToTarget(atof(sep->arg[0]), atof(sep->arg[1]), atof(sep->arg[2]), 0))
|
||||
client->Message(CHANNEL_COLOR_RED, "Invalid coordinates given");
|
||||
|
@ -1647,7 +1648,6 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
client->Message(CHANNEL_COLOR_RED, "Invalid coordinates given");
|
||||
}
|
||||
else {
|
||||
client->ClearWaypoint();
|
||||
client->Message(CHANNEL_COLOR_YELLOW, "Usage: /waypoint x y z");
|
||||
}
|
||||
break;
|
||||
|
@ -3123,16 +3123,13 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
if(type == 0){
|
||||
if(incombat)
|
||||
client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You stop fighting.");
|
||||
player->InCombat(false);
|
||||
player->InCombat(false, true);
|
||||
player->SetRangeAttack(false);
|
||||
player->StopCombat(type);
|
||||
}
|
||||
else {
|
||||
if(type == 2){
|
||||
player->InCombat(false);
|
||||
if(incombat && player->GetRangeAttack()){
|
||||
player->SetRangeAttack(false);
|
||||
player->InCombat(false, true);
|
||||
player->StopCombat(type);
|
||||
client->SimpleMessage(CHANNEL_GENERAL_COMBAT, "You stop fighting.");
|
||||
}
|
||||
else{
|
||||
|
@ -3705,12 +3702,22 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
}
|
||||
break;
|
||||
}
|
||||
else if (ToLower(string(sep->arg[0])) == "pathto")
|
||||
else if (ToLower(string(sep->arg[0])) == "behind")
|
||||
{
|
||||
bool isBehind = client->GetPlayer()->BehindTarget(cmdTarget);
|
||||
client->Message(CHANNEL_COLOR_YELLOW, "%s %s.", isBehind ? "YOU are behind" : "YOU are NOT behind", cmdTarget->GetName());
|
||||
break;
|
||||
}
|
||||
else if (ToLower(string(sep->arg[0])) == "pathfrom")
|
||||
else if (ToLower(string(sep->arg[0])) == "infront")
|
||||
{
|
||||
bool isBehind = client->GetPlayer()->InFrontSpawn(cmdTarget, client->GetPlayer()->GetX(), client->GetPlayer()->GetZ());
|
||||
client->Message(CHANNEL_COLOR_YELLOW, "%s %s.", isBehind ? "YOU are infront of" : "YOU are NOT infront of", cmdTarget->GetName());
|
||||
break;
|
||||
}
|
||||
else if (ToLower(string(sep->arg[0])) == "flank")
|
||||
{
|
||||
bool isFlanking = client->GetPlayer()->FlankingTarget(cmdTarget);
|
||||
client->Message(CHANNEL_COLOR_YELLOW, "%s is %s.", isFlanking ? "YOU are flanking" : "YOU are NOT flanking", cmdTarget->GetName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4571,6 +4578,39 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
case COMMAND_TARGETITEM : { Command_TargetItem(client, sep); break; }
|
||||
case COMMAND_FINDSPAWN: { Command_FindSpawn(client, sep); break; }
|
||||
case COMMAND_MOVECHARACTER: { Command_MoveCharacter(client, sep); break; }
|
||||
case COMMAND_CRAFTITEM: {
|
||||
Item* item = 0;
|
||||
if (sep && sep->IsNumber(0)) {
|
||||
int32 item_id = atol(sep->arg[0]);
|
||||
int32 quantity = 1;
|
||||
|
||||
if (sep->arg[1] && sep->IsNumber(1))
|
||||
quantity = atoi(sep->arg[1]);
|
||||
item = new Item(master_item_list.GetItem(item_id));
|
||||
if (!item) {
|
||||
LogWrite(TRADESKILL__ERROR, 0, "CraftItem", "Item (%u) not found.", item_id);
|
||||
}
|
||||
else {
|
||||
item->details.count = quantity;
|
||||
// use CHANNEL_COLOR_CHAT_RELATIONSHIP as that is the same value (4) as it is in a log for this message
|
||||
client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You created %s.", item->CreateItemLink(client->GetVersion()).c_str());
|
||||
client->AddItem(item);
|
||||
//Check for crafting quest updates
|
||||
int8 update_amt = 0;
|
||||
if (item->stack_count > 1)
|
||||
update_amt = 1;
|
||||
else
|
||||
update_amt = quantity;
|
||||
client->GetPlayer()->CheckQuestsCraftUpdate(item, update_amt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /craftitem {item_id} [quantity] ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
|
@ -10380,6 +10420,10 @@ void Commands::Add_AA(Client* client, Seperator* sep) {
|
|||
spell_tier = client->GetPlayer()->GetSpellTier(spell_id);
|
||||
AltAdvanceData* data = master_aa_list.GetAltAdvancement(spell_id);
|
||||
// addspellbookentry here
|
||||
if(!data) {
|
||||
LogWrite(COMMAND__ERROR, 0, "Command", "Error in Add_AA no data for spell_id %u spell_tier %u", spell_id, spell_tier);
|
||||
return;
|
||||
}
|
||||
if (spell_tier >= data->maxRank) {
|
||||
LogWrite(COMMAND__ERROR, 0, "Command", "Error in Add_AA spell_tier %u >= maxRank %u", spell_tier, data->maxRank);
|
||||
return;
|
||||
|
|
|
@ -872,6 +872,9 @@ private:
|
|||
|
||||
#define COMMAND_MOVECHARACTER 525
|
||||
|
||||
#define COMMAND_CRAFTITEM 526
|
||||
|
||||
|
||||
#define GET_AA_XML 750
|
||||
#define ADD_AA 751
|
||||
#define COMMIT_AA_PROFILE 752
|
||||
|
|
|
@ -28,10 +28,14 @@
|
|||
#include "classes.h"
|
||||
#include "LuaInterface.h"
|
||||
#include "ClientPacketFunctions.h"
|
||||
#include "Skills.h"
|
||||
#include "Rules/Rules.h"
|
||||
|
||||
extern World world;
|
||||
extern MasterItemList master_item_list;
|
||||
extern MasterSpellList master_spell_list;
|
||||
extern MasterSkillList master_skill_list;
|
||||
extern RuleManager rule_manager;
|
||||
extern Classes classes;
|
||||
|
||||
Entity::Entity(){
|
||||
|
@ -77,7 +81,6 @@ Entity::Entity(){
|
|||
MCommandMutex.SetName("Entity::MCommandMutex");
|
||||
hasSeeInvisSpell = false;
|
||||
hasSeeHideSpell = false;
|
||||
|
||||
}
|
||||
|
||||
Entity::~Entity(){
|
||||
|
@ -118,15 +121,15 @@ void Entity::MapInfoStruct()
|
|||
get_int16_funcs["max_mitigation"] = l::bind(&InfoStruct::get_max_mitigation, &info_struct);
|
||||
get_int16_funcs["mitigation_base"] = l::bind(&InfoStruct::get_mitigation_base, &info_struct);
|
||||
get_int16_funcs["avoidance_display"] = l::bind(&InfoStruct::get_avoidance_display, &info_struct);
|
||||
get_int16_funcs["cur_avoidance"] = l::bind(&InfoStruct::get_cur_avoidance, &info_struct);
|
||||
get_float_funcs["cur_avoidance"] = l::bind(&InfoStruct::get_cur_avoidance, &info_struct);
|
||||
get_int16_funcs["base_avoidance_pct"] = l::bind(&InfoStruct::get_base_avoidance_pct, &info_struct);
|
||||
get_int16_funcs["avoidance_base"] = l::bind(&InfoStruct::get_avoidance_base, &info_struct);
|
||||
get_int16_funcs["max_avoidance"] = l::bind(&InfoStruct::get_max_avoidance, &info_struct);
|
||||
get_int16_funcs["parry"] = l::bind(&InfoStruct::get_parry, &info_struct);
|
||||
get_int16_funcs["parry_base"] = l::bind(&InfoStruct::get_parry_base, &info_struct);
|
||||
get_int16_funcs["deflection"] = l::bind(&InfoStruct::get_deflection, &info_struct);
|
||||
get_float_funcs["parry"] = l::bind(&InfoStruct::get_parry, &info_struct);
|
||||
get_float_funcs["parry_base"] = l::bind(&InfoStruct::get_parry_base, &info_struct);
|
||||
get_float_funcs["deflection"] = l::bind(&InfoStruct::get_deflection, &info_struct);
|
||||
get_int16_funcs["deflection_base"] = l::bind(&InfoStruct::get_deflection_base, &info_struct);
|
||||
get_int16_funcs["block"] = l::bind(&InfoStruct::get_block, &info_struct);
|
||||
get_float_funcs["block"] = l::bind(&InfoStruct::get_block, &info_struct);
|
||||
get_int16_funcs["block_base"] = l::bind(&InfoStruct::get_block_base, &info_struct);
|
||||
get_float_funcs["str"] = l::bind(&InfoStruct::get_str, &info_struct);
|
||||
get_float_funcs["sta"] = l::bind(&InfoStruct::get_sta, &info_struct);
|
||||
|
@ -231,6 +234,12 @@ void Entity::MapInfoStruct()
|
|||
get_string_funcs["biography"] = l::bind(&InfoStruct::get_biography, &info_struct);
|
||||
get_float_funcs["drunk"] = l::bind(&InfoStruct::get_drunk, &info_struct);
|
||||
|
||||
get_sint16_funcs["power_regen"] = l::bind(&InfoStruct::get_power_regen, &info_struct);
|
||||
get_sint16_funcs["hp_regen"] = l::bind(&InfoStruct::get_hp_regen, &info_struct);
|
||||
|
||||
get_int8_funcs["power_regen_override"] = l::bind(&InfoStruct::get_power_regen_override, &info_struct);
|
||||
get_int8_funcs["hp_regen_override"] = l::bind(&InfoStruct::get_hp_regen_override, &info_struct);
|
||||
|
||||
|
||||
/** SETS **/
|
||||
set_string_funcs["name"] = l::bind(&InfoStruct::set_name, &info_struct, l::_1);
|
||||
|
@ -252,15 +261,15 @@ void Entity::MapInfoStruct()
|
|||
set_int16_funcs["max_mitigation"] = l::bind(&InfoStruct::set_max_mitigation, &info_struct, l::_1);
|
||||
set_int16_funcs["mitigation_base"] = l::bind(&InfoStruct::set_mitigation_base, &info_struct, l::_1);
|
||||
set_int16_funcs["avoidance_display"] = l::bind(&InfoStruct::set_avoidance_display, &info_struct, l::_1);
|
||||
set_int16_funcs["cur_avoidance"] = l::bind(&InfoStruct::set_cur_avoidance, &info_struct, l::_1);
|
||||
set_float_funcs["cur_avoidance"] = l::bind(&InfoStruct::set_cur_avoidance, &info_struct, l::_1);
|
||||
set_int16_funcs["base_avoidance_pct"] = l::bind(&InfoStruct::set_base_avoidance_pct, &info_struct, l::_1);
|
||||
set_int16_funcs["avoidance_base"] = l::bind(&InfoStruct::set_avoidance_base, &info_struct, l::_1);
|
||||
set_int16_funcs["max_avoidance"] = l::bind(&InfoStruct::set_max_avoidance, &info_struct, l::_1);
|
||||
set_int16_funcs["parry"] = l::bind(&InfoStruct::set_parry, &info_struct, l::_1);
|
||||
set_int16_funcs["parry_base"] = l::bind(&InfoStruct::set_parry_base, &info_struct, l::_1);
|
||||
set_int16_funcs["deflection"] = l::bind(&InfoStruct::set_deflection, &info_struct, l::_1);
|
||||
set_float_funcs["parry"] = l::bind(&InfoStruct::set_parry, &info_struct, l::_1);
|
||||
set_float_funcs["parry_base"] = l::bind(&InfoStruct::set_parry_base, &info_struct, l::_1);
|
||||
set_float_funcs["deflection"] = l::bind(&InfoStruct::set_deflection, &info_struct, l::_1);
|
||||
set_int16_funcs["deflection_base"] = l::bind(&InfoStruct::set_deflection_base, &info_struct, l::_1);
|
||||
set_int16_funcs["block"] = l::bind(&InfoStruct::set_block, &info_struct, l::_1);
|
||||
set_float_funcs["block"] = l::bind(&InfoStruct::set_block, &info_struct, l::_1);
|
||||
set_int16_funcs["block_base"] = l::bind(&InfoStruct::set_block_base, &info_struct, l::_1);
|
||||
set_float_funcs["str"] = l::bind(&InfoStruct::set_str, &info_struct, l::_1);
|
||||
set_float_funcs["sta"] = l::bind(&InfoStruct::set_sta, &info_struct, l::_1);
|
||||
|
@ -365,6 +374,12 @@ void Entity::MapInfoStruct()
|
|||
set_string_funcs["biography"] = l::bind(&InfoStruct::set_biography, &info_struct, l::_1);
|
||||
set_float_funcs["drunk"] = l::bind(&InfoStruct::set_drunk, &info_struct, l::_1);
|
||||
|
||||
set_sint16_funcs["power_regen"] = l::bind(&InfoStruct::set_power_regen, &info_struct, l::_1);
|
||||
set_sint16_funcs["hp_region"] = l::bind(&InfoStruct::set_hp_regen, &info_struct, l::_1);
|
||||
|
||||
set_int8_funcs["power_regen_override"] = l::bind(&InfoStruct::set_power_regen_override, &info_struct, l::_1);
|
||||
set_int8_funcs["hp_region_override"] = l::bind(&InfoStruct::set_hp_regen_override, &info_struct, l::_1);
|
||||
|
||||
}
|
||||
|
||||
bool Entity::HasMoved(bool include_heading){
|
||||
|
@ -667,55 +682,11 @@ int8 Entity::GetWieldType(){
|
|||
}
|
||||
|
||||
bool Entity::BehindTarget(Spawn* target){
|
||||
float target_angle = 360 - target->GetHeading();
|
||||
float angle = 360 - GetHeading();
|
||||
if(target_angle > angle)
|
||||
angle = target_angle - angle;
|
||||
else
|
||||
angle -= target_angle;
|
||||
return (angle < 90 || angle > 270);
|
||||
return BehindSpawn(target, GetX(), GetZ());
|
||||
}
|
||||
|
||||
bool Entity::FlankingTarget(Spawn* target) {
|
||||
float angle;
|
||||
double diff_x = target->GetX() - GetX();
|
||||
double diff_z = target->GetZ() - GetZ();
|
||||
if (diff_z == 0) {
|
||||
if (diff_x > 0)
|
||||
angle = 90;
|
||||
else
|
||||
angle = 270;
|
||||
}
|
||||
else
|
||||
angle = ((atan(diff_x / diff_z)) * 180) / 3.14159265358979323846;
|
||||
if (angle < 0)
|
||||
angle = angle + 360;
|
||||
else
|
||||
angle = angle + 180;
|
||||
if (diff_x < 0)
|
||||
angle = angle + 180;
|
||||
|
||||
if (angle > GetHeading())
|
||||
angle = angle - GetHeading();
|
||||
else
|
||||
angle = GetHeading() - angle;
|
||||
|
||||
if (angle > 360)
|
||||
angle -= 360;
|
||||
|
||||
//LogWrite(SPAWN__ERROR, 0, "Angle", "spawn heading = %f", GetHeading());
|
||||
//LogWrite(SPAWN__ERROR, 0, "Angle", "angle = %f", angle);
|
||||
|
||||
return (angle >= 45 && angle <= 315);
|
||||
}
|
||||
|
||||
float Entity::GetShieldBlockChance(){
|
||||
float ret = 0;
|
||||
Item* item = equipment_list.GetItem(1);
|
||||
if(item && item->details.item_id > 0 && item->IsShield()){
|
||||
|
||||
}
|
||||
return ret;
|
||||
return IsFlankingSpawn(target, GetX(), GetZ());
|
||||
}
|
||||
|
||||
float Entity::GetDodgeChance(){
|
||||
|
@ -729,20 +700,14 @@ bool Entity::EngagedInCombat(){
|
|||
}
|
||||
|
||||
void Entity::InCombat(bool val){
|
||||
in_combat = val;
|
||||
}
|
||||
bool changeCombatState = false;
|
||||
if((in_combat && !val) || (!in_combat && val))
|
||||
changeCombatState = true;
|
||||
|
||||
void Entity::SetHPRegen(int16 new_val){
|
||||
regen_hp_rate = new_val;
|
||||
}
|
||||
void Entity::SetPowerRegen(int16 new_val){
|
||||
regen_power_rate = new_val;
|
||||
}
|
||||
int16 Entity::GetHPRegen(){
|
||||
return regen_hp_rate;
|
||||
}
|
||||
int16 Entity::GetPowerRegen(){
|
||||
return regen_power_rate;
|
||||
in_combat = val;
|
||||
|
||||
if(changeCombatState)
|
||||
SetRegenValues(GetInfoStruct()->get_effective_level());
|
||||
}
|
||||
|
||||
void Entity::DoRegenUpdate(){
|
||||
|
@ -751,19 +716,9 @@ void Entity::DoRegenUpdate(){
|
|||
sint32 hp = GetHP();
|
||||
sint32 power = GetPower();
|
||||
|
||||
int16 effective_level = GetInfoStruct()->get_effective_level();
|
||||
if(!effective_level)
|
||||
effective_level = GetLevel();
|
||||
|
||||
// No regen for NPC's while in combat
|
||||
// Temp solution for now
|
||||
if (IsNPC() && EngagedInCombat())
|
||||
return;
|
||||
|
||||
if(hp < GetTotalHP()){
|
||||
if(regen_hp_rate == 0)
|
||||
regen_hp_rate = (int)(effective_level*.75)+(int)(effective_level/10) + 1;
|
||||
int16 temp = regen_hp_rate + stats[ITEM_STAT_HPREGEN];
|
||||
sint16 temp = GetInfoStruct()->get_hp_regen();
|
||||
|
||||
if((hp + temp) > GetTotalHP())
|
||||
SetHP(GetTotalHP());
|
||||
else
|
||||
|
@ -773,16 +728,14 @@ void Entity::DoRegenUpdate(){
|
|||
|
||||
}
|
||||
if(GetPower() < GetTotalPower()){
|
||||
if(regen_power_rate == 0)
|
||||
regen_power_rate = effective_level + (int)(effective_level/10) + 1;
|
||||
cout << "regen_power_rate: " << regen_power_rate << endl;
|
||||
if((power + regen_power_rate) > GetTotalPower())
|
||||
sint16 temp = GetInfoStruct()->get_power_regen();
|
||||
|
||||
if((power + temp) > GetTotalPower())
|
||||
SetPower(GetTotalPower());
|
||||
else
|
||||
SetPower(power + regen_power_rate);
|
||||
SetPower(power + temp);
|
||||
|
||||
LogWrite(MISC__TODO, 1, "TODO", "Fix this later for mobs\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,8 +932,39 @@ void Entity::SetMaxSpeed(float val){
|
|||
max_speed = val;
|
||||
}
|
||||
|
||||
float Entity::CalculateSkillStatChance(char* skillName, int16 item_stat, float max_cap, float modifier, bool add_to_skill)
|
||||
{
|
||||
float skillAndItemsChance = 0.0f;
|
||||
|
||||
Skill* skill = GetSkillByName(skillName, false);
|
||||
if(skill){
|
||||
MStats.lock();
|
||||
float item_chance_or_skill = stats[item_stat];
|
||||
MStats.unlock();
|
||||
if(add_to_skill)
|
||||
{
|
||||
skillAndItemsChance = (((float)skill->current_val+item_chance_or_skill)/10.0f); // do we know 25 is accurate? 10 gives more 'skill' space, most cap at 70% with items
|
||||
}
|
||||
else
|
||||
{
|
||||
skillAndItemsChance = ((float)skill->current_val/10.0f); // do we know 25 is accurate? 10 gives more 'skill' space, most cap at 70% with items
|
||||
|
||||
// take chance percentage and add the item stats % (+1 = 1% or .01f)
|
||||
skillAndItemsChance += (skillAndItemsChance*((item_chance_or_skill + modifier)/100.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if ( max_cap > 0.0f && skillAndItemsChance > max_cap )
|
||||
skillAndItemsChance = max_cap;
|
||||
|
||||
return skillAndItemsChance;
|
||||
}
|
||||
|
||||
void Entity::CalculateBonuses(){
|
||||
InfoStruct* info = &info_struct;
|
||||
|
||||
int16 effective_level = info->get_effective_level() != 0 ? info->get_effective_level() : GetLevel();
|
||||
|
||||
info->set_block(info->get_block_base());
|
||||
|
||||
info->set_cur_attack(info->get_attack_base());
|
||||
|
@ -989,10 +973,6 @@ void Entity::CalculateBonuses(){
|
|||
|
||||
LogWrite(MISC__TODO, 1, "TODO", "Calculate via current spells\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
//info->cur_concentration = 0;
|
||||
info->set_parry(info->get_parry_base());
|
||||
info->set_deflection(info->get_deflection_base());
|
||||
|
||||
info->set_disease(info->get_disease_base());
|
||||
info->set_divine(info->get_divine_base());
|
||||
info->set_heat(info->get_heat_base());
|
||||
|
@ -1102,9 +1082,173 @@ void Entity::CalculateBonuses(){
|
|||
info->add_uncontested_parry(values->uncontested_parry);
|
||||
info->add_uncontested_dodge(values->uncontested_dodge);
|
||||
info->add_uncontested_riposte(values->uncontested_riposte);
|
||||
|
||||
|
||||
float full_pct_hit = 100.0f;
|
||||
|
||||
//info->cur_concentration = 0;
|
||||
MStats.lock();
|
||||
float parryStat = stats[ITEM_STAT_PARRY];
|
||||
MStats.unlock();
|
||||
float parry_pct = CalculateSkillStatChance("Parry", ITEM_STAT_PARRYCHANCE, 70.0f, parryStat);
|
||||
parry_pct += parry_pct * (info->get_cur_avoidance()/100.0f);
|
||||
if(parry_pct > 70.0f)
|
||||
parry_pct = 70.0f;
|
||||
|
||||
info->set_parry(parry_pct);
|
||||
|
||||
full_pct_hit -= parry_pct;
|
||||
|
||||
float block_pct = 0.0f;
|
||||
|
||||
if(GetAdventureClass() != BRAWLER)
|
||||
{
|
||||
Item* item = equipment_list.GetItem(EQ2_SECONDARY_SLOT);
|
||||
if(item && item->details.item_id > 0 && item->IsShield()){
|
||||
// if high is set and greater than low use high, otherwise use low
|
||||
int16 mitigation = item->armor_info->mitigation_high > item->armor_info->mitigation_low ? item->armor_info->mitigation_high : item->armor_info->mitigation_low;
|
||||
// we frankly don't know the formula for Block, only that it uses the 'Protection' of the shield, which is the mitigation_low/mitigation_high in the armor_info
|
||||
if(mitigation)
|
||||
{
|
||||
/*DOF Prima Guide: Shields now have the following base chances
|
||||
to block: Tower (10%), Kite (10%), Round
|
||||
(5%), Buckler (3%). Your chances to block
|
||||
scale up or down based on the con of your
|
||||
opponent.*/
|
||||
Skill* skill = master_skill_list.GetSkill(item->generic_info.skill_req1);
|
||||
float baseBlock = 0.0f;
|
||||
if(skill)
|
||||
{
|
||||
if(skill->short_name.data == "towershield" || skill->short_name.data == "kiteshield")
|
||||
baseBlock = 10.0f;
|
||||
else if (skill->short_name.data == "roundshield")
|
||||
baseBlock = 5.0f;
|
||||
else if (skill->short_name.data == "buckler")
|
||||
baseBlock = 3.0f;
|
||||
}
|
||||
if(GetLevel() > mitigation)
|
||||
block_pct = log10f((float)mitigation/((float)GetLevel()*10.0f));
|
||||
else
|
||||
block_pct = log10f(((float)GetLevel()/(float)mitigation)) * log10f(GetLevel()) * 2.0f;
|
||||
|
||||
if(block_pct < 0.0f)
|
||||
block_pct *= -1.0f;
|
||||
|
||||
block_pct += baseBlock;
|
||||
|
||||
block_pct += block_pct * (info->get_cur_avoidance()/100.0f);
|
||||
if(block_pct > 70.0f)
|
||||
block_pct = 70.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//info->cur_concentration = 0;
|
||||
MStats.lock();
|
||||
float deflectionStat = stats[ITEM_STAT_DEFLECTION];
|
||||
MStats.unlock();
|
||||
block_pct = CalculateSkillStatChance("Deflection", ITEM_STAT_MINIMUMDEFLECTIONCHANCE, 70.0f, deflectionStat+1.0f);
|
||||
block_pct += block_pct * (info->get_cur_avoidance()/100.0f);
|
||||
}
|
||||
|
||||
float block_actual = 0.0f;
|
||||
if(full_pct_hit > 0.0f)
|
||||
block_actual = block_pct * (full_pct_hit / 100.0f);
|
||||
|
||||
info->set_block(block_actual);
|
||||
full_pct_hit -= block_actual;
|
||||
|
||||
|
||||
//info->cur_concentration = 0;
|
||||
MStats.lock();
|
||||
float defenseStat = stats[ITEM_STAT_DEFENSE];
|
||||
MStats.unlock();
|
||||
|
||||
float dodge_pct = CalculateSkillStatChance("Defense", ITEM_STAT_DODGECHANCE, 100.0f, defenseStat);
|
||||
dodge_pct += dodge_pct * (info->get_cur_avoidance()/100.0f);
|
||||
|
||||
float dodge_actual = 0.0f;
|
||||
if(full_pct_hit > 0.0f)
|
||||
dodge_actual = dodge_pct * (full_pct_hit / 100.0f) + (log10f(GetLevel() * GetAgi()) / 100.0f);
|
||||
|
||||
info->set_avoidance_base(dodge_actual);
|
||||
|
||||
float total_avoidance = parry_pct + block_actual + dodge_actual;
|
||||
info->set_avoidance_display(total_avoidance);
|
||||
|
||||
SetRegenValues(effective_level);
|
||||
|
||||
safe_delete(values);
|
||||
}
|
||||
|
||||
void Entity::SetRegenValues(int16 effective_level)
|
||||
{
|
||||
bool classicRegen = rule_manager.GetGlobalRule(R_Spawn, ClassicRegen)->GetBool();
|
||||
if(!GetInfoStruct()->get_hp_regen_override())
|
||||
{
|
||||
sint16 regen_hp_rate = 0;
|
||||
sint16 temp = 0;
|
||||
|
||||
MStats.lock();
|
||||
if(!IsAggroed())
|
||||
{
|
||||
if(classicRegen)
|
||||
{
|
||||
// classic regen only gives OUT OF COMBAT, doesn't combine in+out of combat
|
||||
regen_hp_rate = (int)(effective_level*.75)+1;
|
||||
temp = regen_hp_rate + stats[ITEM_STAT_HPREGEN];
|
||||
temp += stats[ITEM_STAT_HPREGENPPT];
|
||||
}
|
||||
else
|
||||
{
|
||||
regen_hp_rate = (int)(effective_level*.75)+(int)(effective_level/10) + 1;
|
||||
temp = regen_hp_rate + stats[ITEM_STAT_HPREGEN];
|
||||
temp += stats[ITEM_STAT_HPREGENPPT] + stats[ITEM_STAT_COMBATHPREGENPPT];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regen_hp_rate = (sint16)(effective_level / 10) + 1;
|
||||
temp = regen_hp_rate + stats[ITEM_STAT_COMBATHPREGENPPT];
|
||||
}
|
||||
MStats.unlock();
|
||||
|
||||
GetInfoStruct()->set_hp_regen(temp);
|
||||
}
|
||||
|
||||
if(!GetInfoStruct()->get_power_regen_override())
|
||||
{
|
||||
sint16 regen_power_rate = 0;
|
||||
sint16 temp = 0;
|
||||
|
||||
MStats.lock();
|
||||
if(!IsAggroed())
|
||||
{
|
||||
if(classicRegen)
|
||||
{
|
||||
regen_power_rate = effective_level + 1;
|
||||
temp = regen_power_rate + stats[ITEM_STAT_MANAREGEN];
|
||||
temp += stats[ITEM_STAT_MPREGENPPT];
|
||||
}
|
||||
else
|
||||
{
|
||||
regen_power_rate = effective_level + (int)(effective_level/10) + 1;
|
||||
temp = regen_power_rate + stats[ITEM_STAT_MANAREGEN];
|
||||
temp += stats[ITEM_STAT_MPREGENPPT] + stats[ITEM_STAT_COMBATMPREGENPPT];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regen_power_rate = (sint16)(effective_level / 10) + 1;
|
||||
temp = regen_power_rate + stats[ITEM_STAT_COMBATMPREGENPPT];
|
||||
}
|
||||
MStats.unlock();
|
||||
|
||||
GetInfoStruct()->set_power_regen(temp);
|
||||
}
|
||||
}
|
||||
|
||||
EquipmentItemList* Entity::GetEquipmentList(){
|
||||
return &equipment_list;
|
||||
}
|
||||
|
@ -1664,6 +1808,7 @@ float Entity::GetSpeed() {
|
|||
if (EngagedInCombat() && GetMaxSpeed() > 0.0f)
|
||||
ret = GetMaxSpeed();
|
||||
|
||||
MStats.lock();
|
||||
if ((IsStealthed() || IsInvis()) && stats.count(ITEM_STAT_STEALTHINVISSPEEDMOD))
|
||||
ret += stats[ITEM_STAT_STEALTHINVISSPEEDMOD];
|
||||
else if (EngagedInCombat() && stats.count(ITEM_STAT_OFFENSIVESPEED))
|
||||
|
@ -1674,6 +1819,7 @@ float Entity::GetSpeed() {
|
|||
ret += stats[ITEM_STAT_SPEED];
|
||||
else if (stats.count(ITEM_STAT_MOUNTSPEED))
|
||||
ret += stats[ITEM_STAT_MOUNTSPEED];
|
||||
MStats.unlock();
|
||||
|
||||
ret *= speed_multiplier;
|
||||
return ret;
|
||||
|
|
|
@ -133,12 +133,12 @@ struct InfoStruct{
|
|||
max_mitigation_ = 0;
|
||||
mitigation_base_ = 0;
|
||||
avoidance_display_ = 0;
|
||||
cur_avoidance_ = 0;
|
||||
cur_avoidance_ = 0.0f;
|
||||
base_avoidance_pct_ = 0;
|
||||
avoidance_base_ = 0;
|
||||
max_avoidance_ = 0;
|
||||
parry_ = 0;
|
||||
parry_base_ = 0;
|
||||
parry_ = 0.0f;
|
||||
parry_base_ = 0.0f;
|
||||
deflection_ = 0;
|
||||
deflection_base_ = 0;
|
||||
block_ = 0;
|
||||
|
@ -246,7 +246,11 @@ struct InfoStruct{
|
|||
breathe_underwater_ = 0;
|
||||
biography_ = std::string("");
|
||||
drunk_ = 0;
|
||||
power_regen_ = 0;
|
||||
hp_regen_ = 0;
|
||||
|
||||
power_regen_override_ = 0;
|
||||
hp_regen_override_ = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -388,7 +392,11 @@ struct InfoStruct{
|
|||
breathe_underwater_ = oldStruct->get_breathe_underwater();
|
||||
biography_ = std::string(oldStruct->get_biography());
|
||||
drunk_ = oldStruct->get_drunk();
|
||||
power_regen_ = oldStruct->get_power_regen();
|
||||
hp_regen_ = oldStruct->get_hp_regen();
|
||||
|
||||
power_regen_override_ = oldStruct->get_power_regen_override();
|
||||
hp_regen_override_ = oldStruct->get_hp_regen_override();
|
||||
}
|
||||
|
||||
//mutable std::shared_mutex mutex_;
|
||||
|
@ -413,19 +421,19 @@ struct InfoStruct{
|
|||
|
||||
int16 get_mitigation_base() { std::lock_guard<std::mutex> lk(classMutex); return mitigation_base_; }
|
||||
int16 get_avoidance_display() { std::lock_guard<std::mutex> lk(classMutex); return avoidance_display_; }
|
||||
int16 get_cur_avoidance() { std::lock_guard<std::mutex> lk(classMutex); return cur_avoidance_; }
|
||||
float get_cur_avoidance() { std::lock_guard<std::mutex> lk(classMutex); return cur_avoidance_; }
|
||||
int16 get_base_avoidance_pct() { std::lock_guard<std::mutex> lk(classMutex); return base_avoidance_pct_; }
|
||||
int16 get_avoidance_base() { std::lock_guard<std::mutex> lk(classMutex); return avoidance_base_; }
|
||||
|
||||
int16 get_parry() { std::lock_guard<std::mutex> lk(classMutex); return parry_; }
|
||||
int16 get_parry_base() { std::lock_guard<std::mutex> lk(classMutex); return parry_base_; }
|
||||
float get_parry() { std::lock_guard<std::mutex> lk(classMutex); return parry_; }
|
||||
float get_parry_base() { std::lock_guard<std::mutex> lk(classMutex); return parry_base_; }
|
||||
|
||||
int16 get_max_avoidance() { std::lock_guard<std::mutex> lk(classMutex); return max_avoidance_; }
|
||||
|
||||
int16 get_deflection() { std::lock_guard<std::mutex> lk(classMutex); return deflection_; }
|
||||
float get_deflection() { std::lock_guard<std::mutex> lk(classMutex); return deflection_; }
|
||||
int16 get_deflection_base() { std::lock_guard<std::mutex> lk(classMutex); return deflection_base_; }
|
||||
|
||||
int16 get_block() { std::lock_guard<std::mutex> lk(classMutex); return block_; }
|
||||
float get_block() { std::lock_guard<std::mutex> lk(classMutex); return block_; }
|
||||
int16 get_block_base() { std::lock_guard<std::mutex> lk(classMutex); return block_base_; }
|
||||
|
||||
float get_str() { std::lock_guard<std::mutex> lk(classMutex); return str_; }
|
||||
|
@ -540,6 +548,12 @@ struct InfoStruct{
|
|||
std::string get_biography() { std::lock_guard<std::mutex> lk(classMutex); return biography_; }
|
||||
float get_drunk() { std::lock_guard<std::mutex> lk(classMutex); return drunk_; }
|
||||
|
||||
sint16 get_power_regen() { std::lock_guard<std::mutex> lk(classMutex); return power_regen_; }
|
||||
sint16 get_hp_regen() { std::lock_guard<std::mutex> lk(classMutex); return hp_regen_; }
|
||||
|
||||
int8 get_power_regen_override() { std::lock_guard<std::mutex> lk(classMutex); return power_regen_override_; }
|
||||
int8 get_hp_regen_override() { std::lock_guard<std::mutex> lk(classMutex); return hp_regen_override_; }
|
||||
|
||||
void set_name(std::string value) { std::lock_guard<std::mutex> lk(classMutex); name_ = value; }
|
||||
|
||||
void set_deity(std::string value) { std::lock_guard<std::mutex> lk(classMutex); deity_ = value; }
|
||||
|
@ -568,15 +582,15 @@ struct InfoStruct{
|
|||
void add_mitigation_base(int16 value) { std::lock_guard<std::mutex> lk(classMutex); mitigation_base_ += value; }
|
||||
|
||||
void set_avoidance_display(int16 value) { std::lock_guard<std::mutex> lk(classMutex); avoidance_display_ = value; }
|
||||
void set_cur_avoidance(int16 value) { std::lock_guard<std::mutex> lk(classMutex); cur_avoidance_ = value; }
|
||||
void set_cur_avoidance(float value) { std::lock_guard<std::mutex> lk(classMutex); cur_avoidance_ = value; }
|
||||
void set_base_avoidance_pct(int16 value) { std::lock_guard<std::mutex> lk(classMutex); base_avoidance_pct_ = value; }
|
||||
void set_avoidance_base(int16 value) { std::lock_guard<std::mutex> lk(classMutex); avoidance_base_ = value; }
|
||||
void set_max_avoidance(int16 value) { std::lock_guard<std::mutex> lk(classMutex); max_avoidance_ = value; }
|
||||
void set_parry(int16 value) { std::lock_guard<std::mutex> lk(classMutex); parry_ = value; }
|
||||
void set_parry_base(int16 value) { std::lock_guard<std::mutex> lk(classMutex); parry_base_ = value; }
|
||||
void set_parry(float value) { std::lock_guard<std::mutex> lk(classMutex); parry_ = value; }
|
||||
void set_parry_base(float value) { std::lock_guard<std::mutex> lk(classMutex); parry_base_ = value; }
|
||||
void set_deflection(int16 value) { std::lock_guard<std::mutex> lk(classMutex); deflection_ = value; }
|
||||
void set_deflection_base(int16 value) { std::lock_guard<std::mutex> lk(classMutex); deflection_base_ = value; }
|
||||
void set_block(int16 value) { std::lock_guard<std::mutex> lk(classMutex); block_ = value; }
|
||||
void set_deflection_base(float value) { std::lock_guard<std::mutex> lk(classMutex); deflection_base_ = value; }
|
||||
void set_block(float value) { std::lock_guard<std::mutex> lk(classMutex); block_ = value; }
|
||||
void set_block_base(int16 value) { std::lock_guard<std::mutex> lk(classMutex); block_base_ = value; }
|
||||
|
||||
void set_str(float value) { std::lock_guard<std::mutex> lk(classMutex); str_ = value; }
|
||||
|
@ -773,6 +787,12 @@ struct InfoStruct{
|
|||
|
||||
void set_biography(std::string value) { std::lock_guard<std::mutex> lk(classMutex); biography_ = value; }
|
||||
|
||||
void set_power_regen(sint16 value) { std::lock_guard<std::mutex> lk(classMutex); power_regen_ = value; }
|
||||
void set_hp_regen(sint16 value) { std::lock_guard<std::mutex> lk(classMutex); hp_regen_ = value; }
|
||||
|
||||
void set_power_regen_override(int8 value) { std::lock_guard<std::mutex> lk(classMutex); power_regen_override_ = value; }
|
||||
void set_hp_regen_override(int8 value) { std::lock_guard<std::mutex> lk(classMutex); hp_regen_override_ = value; }
|
||||
|
||||
void ResetEffects(Spawn* spawn)
|
||||
{
|
||||
for(int i=0;i<45;i++){
|
||||
|
@ -811,16 +831,18 @@ private:
|
|||
int16 max_mitigation_;
|
||||
int16 mitigation_base_;
|
||||
int16 avoidance_display_;
|
||||
int16 cur_avoidance_;
|
||||
float cur_avoidance_;
|
||||
int16 base_avoidance_pct_;
|
||||
int16 avoidance_base_;
|
||||
int16 max_avoidance_;
|
||||
int16 parry_;
|
||||
int16 parry_base_;
|
||||
int16 deflection_;
|
||||
float parry_;
|
||||
float parry_base_;
|
||||
float deflection_;
|
||||
int16 deflection_base_;
|
||||
int16 block_;
|
||||
float block_;
|
||||
int16 block_base_;
|
||||
float riposte_;
|
||||
float riposte_base_;
|
||||
float str_; //int16
|
||||
float sta_; //int16
|
||||
float agi_;//int16
|
||||
|
@ -928,6 +950,11 @@ private:
|
|||
std::string biography_;
|
||||
float drunk_;
|
||||
|
||||
sint16 power_regen_;
|
||||
sint16 hp_regen_;
|
||||
|
||||
int8 power_regen_override_;
|
||||
int8 hp_regen_override_;
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex classMutex;
|
||||
};
|
||||
|
@ -1034,7 +1061,6 @@ public:
|
|||
virtual ~Entity();
|
||||
|
||||
void MapInfoStruct();
|
||||
virtual float GetShieldBlockChance();
|
||||
virtual float GetDodgeChance();
|
||||
virtual void AddMaintainedSpell(LuaSpell* spell);
|
||||
virtual void AddSpellEffect(LuaSpell* spell);
|
||||
|
@ -1054,7 +1080,9 @@ public:
|
|||
EquipmentItemList* GetEquipmentList();
|
||||
|
||||
bool IsEntity(){ return true; }
|
||||
float CalculateSkillStatChance(char* skill, int16 item_stat, float max_cap = 0.0f, float modifier = 0.0f, bool add_to_skill = false);
|
||||
void CalculateBonuses();
|
||||
void SetRegenValues(int16 effective_level);
|
||||
float CalculateBonusMod();
|
||||
float CalculateDPSMultiplier();
|
||||
float CalculateCastingSpeedMod();
|
||||
|
@ -1098,9 +1126,7 @@ public:
|
|||
|
||||
bool HasMoved(bool include_heading);
|
||||
void SetHPRegen(int16 new_val);
|
||||
void SetPowerRegen(int16 new_val);
|
||||
int16 GetHPRegen();
|
||||
int16 GetPowerRegen();
|
||||
void DoRegenUpdate();
|
||||
MaintainedEffects* GetFreeMaintainedSpellSlot();
|
||||
SpellEffects* GetFreeSpellEffectSlot();
|
||||
|
@ -1499,6 +1525,17 @@ public:
|
|||
|
||||
// Keep track of entities that hate this spawn.
|
||||
set<int32> HatedBy;
|
||||
std::mutex MHatedBy;
|
||||
|
||||
bool IsAggroed() {
|
||||
int32 size = 0;
|
||||
|
||||
MHatedBy.lock();
|
||||
size = HatedBy.size();
|
||||
MHatedBy.unlock();
|
||||
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
Mutex MCommandMutex;
|
||||
|
||||
|
@ -1539,6 +1576,7 @@ public:
|
|||
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex MEquipment;
|
||||
std::mutex MStats;
|
||||
protected:
|
||||
bool in_combat;
|
||||
|
||||
|
|
|
@ -132,6 +132,15 @@ void GroundSpawn::ProcessHarvest(Client* client) {
|
|||
return;
|
||||
}
|
||||
|
||||
int16 totalSkill = skill->current_val;
|
||||
int32 skillID = master_item_list.GetItemStatIDByName(collection_skill);
|
||||
if(skillID != 0xFFFFFFFF)
|
||||
{
|
||||
((Entity*)client->GetPlayer())->MStats.lock();
|
||||
totalSkill += ((Entity*)client->GetPlayer())->stats[skillID];
|
||||
((Entity*)client->GetPlayer())->MStats.unlock();
|
||||
}
|
||||
|
||||
for (int8 i = 0; i < num_attempts_per_harvest; i++) {
|
||||
vector<GroundSpawnEntry*> mod_groundspawn_entries;
|
||||
|
||||
|
@ -147,7 +156,7 @@ void GroundSpawn::ProcessHarvest(Client* client) {
|
|||
entry = *itr;
|
||||
|
||||
// if player lacks skill, skip table
|
||||
if (entry->min_skill_level > skill->current_val)
|
||||
if (entry->min_skill_level > totalSkill)
|
||||
continue;
|
||||
// if bonus, but player lacks level, skip table
|
||||
if (entry->bonus_table && (client->GetPlayer()->GetLevel() < entry->min_adventure_level))
|
||||
|
@ -182,7 +191,7 @@ void GroundSpawn::ProcessHarvest(Client* client) {
|
|||
}
|
||||
|
||||
// now roll to see which table to use
|
||||
table_choice = MakeRandomInt(lowest_skill_level, skill->current_val);
|
||||
table_choice = MakeRandomInt(lowest_skill_level, totalSkill);
|
||||
LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Random INT for Table by skill level: %i", table_choice);
|
||||
|
||||
int16 highest_score = 0;
|
||||
|
@ -251,7 +260,7 @@ void GroundSpawn::ProcessHarvest(Client* client) {
|
|||
harvest_type = 2;
|
||||
reward_total = 3;
|
||||
}
|
||||
else if (chance <= selected_table->harvest1 || skill->current_val == skill->max_val || is_collection) {
|
||||
else if (chance <= selected_table->harvest1 || totalSkill >= skill->max_val || is_collection) {
|
||||
LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest 1 Item from table : %i", selected_table->min_skill_level);
|
||||
harvest_type = 1;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../Recipes/Recipe.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
extern World world;
|
||||
extern MasterSpellList master_spell_list;
|
||||
|
@ -38,6 +39,49 @@ extern MasterRecipeList master_recipe_list;
|
|||
extern ConfigReader configReader;
|
||||
extern LuaInterface* lua_interface;
|
||||
|
||||
MasterItemList::MasterItemList(){
|
||||
AddMappedItemStat(ITEM_STAT_ADORNING, std::string("adorning"));
|
||||
AddMappedItemStat(ITEM_STAT_AGGRESSION, std::string("aggression"));
|
||||
AddMappedItemStat(ITEM_STAT_ARTIFICING, std::string("artificing"));
|
||||
AddMappedItemStat(ITEM_STAT_ARTISTRY, std::string("artistry"));
|
||||
AddMappedItemStat(ITEM_STAT_CHEMISTRY, std::string("chemistry"));
|
||||
AddMappedItemStat(ITEM_STAT_CRUSHING, std::string("crushing"));
|
||||
AddMappedItemStat(ITEM_STAT_DEFENSE, std::string("defense"));
|
||||
AddMappedItemStat(ITEM_STAT_DEFLECTION, std::string("deflection"));
|
||||
AddMappedItemStat(ITEM_STAT_DISRUPTION, std::string("disruption"));
|
||||
AddMappedItemStat(ITEM_STAT_FISHING, std::string("fishing"));
|
||||
AddMappedItemStat(ITEM_STAT_FLETCHING, std::string("fletching"));
|
||||
AddMappedItemStat(ITEM_STAT_FOCUS, std::string("focus"));
|
||||
AddMappedItemStat(ITEM_STAT_FORESTING, std::string("foresting"));
|
||||
AddMappedItemStat(ITEM_STAT_GATHERING, std::string("gathering"));
|
||||
AddMappedItemStat(ITEM_STAT_METAL_SHAPING, std::string("metal shaping"));
|
||||
AddMappedItemStat(ITEM_STAT_METALWORKING, std::string("metalworking"));
|
||||
AddMappedItemStat(ITEM_STAT_MINING, std::string("mining"));
|
||||
AddMappedItemStat(ITEM_STAT_MINISTRATION, std::string("ministration"));
|
||||
AddMappedItemStat(ITEM_STAT_ORDINATION, std::string("ordination"));
|
||||
AddMappedItemStat(ITEM_STAT_ADORNING, std::string("adorning"));
|
||||
AddMappedItemStat(ITEM_STAT_PARRY, std::string("parry"));
|
||||
AddMappedItemStat(ITEM_STAT_PIERCING, std::string("piercing"));
|
||||
AddMappedItemStat(ITEM_STAT_RANGED, std::string("ranged"));
|
||||
AddMappedItemStat(ITEM_STAT_SAFE_FALL, std::string("safe fall"));
|
||||
AddMappedItemStat(ITEM_STAT_SCRIBING, std::string("scribing"));
|
||||
AddMappedItemStat(ITEM_STAT_SCULPTING, std::string("sculpting"));
|
||||
AddMappedItemStat(ITEM_STAT_SLASHING, std::string("slashing"));
|
||||
AddMappedItemStat(ITEM_STAT_SUBJUGATION, std::string("subjugation"));
|
||||
AddMappedItemStat(ITEM_STAT_SWIMMING, std::string("swimming"));
|
||||
AddMappedItemStat(ITEM_STAT_TAILORING, std::string("tailoring"));
|
||||
AddMappedItemStat(ITEM_STAT_TINKERING, std::string("tinkering"));
|
||||
AddMappedItemStat(ITEM_STAT_TRANSMUTING, std::string("transmuting"));
|
||||
AddMappedItemStat(ITEM_STAT_TRAPPING, std::string("trapping"));
|
||||
AddMappedItemStat(ITEM_STAT_WEAPON_SKILLS, std::string("weapon skills"));
|
||||
}
|
||||
|
||||
void MasterItemList::AddMappedItemStat(int32 id, std::string lower_case_name)
|
||||
{
|
||||
mappedItemStatsStrings[lower_case_name] = id;
|
||||
mappedItemStatTypeIDs[id] = lower_case_name;
|
||||
}
|
||||
|
||||
MasterItemList::~MasterItemList(){
|
||||
RemoveAll();
|
||||
}
|
||||
|
@ -707,7 +751,28 @@ ItemStatsValues* MasterItemList::CalculateItemBonuses(Item* item, Entity* entity
|
|||
}
|
||||
for(int32 i=0;i<item->item_stats.size();i++){
|
||||
ItemStat* stat = item->item_stats[i];
|
||||
world.AddBonuses(values, stat->stat_type*100 + stat->stat_subtype, stat->value, entity);
|
||||
int multiplier = 100;
|
||||
if(stat->stat_subtype > 99)
|
||||
multiplier = 1000;
|
||||
|
||||
int32 id = 0;
|
||||
sint32 value = stat->value;
|
||||
if(stat->stat_type != 1)
|
||||
id = stat->stat_type*multiplier + stat->stat_subtype;
|
||||
else
|
||||
{
|
||||
int32 tmp_id = master_item_list.GetItemStatIDByName(stat->stat_name);
|
||||
if(tmp_id != 0xFFFFFFFF)
|
||||
{
|
||||
id = tmp_id;
|
||||
if(!value)
|
||||
value = stat->stat_subtype;
|
||||
}
|
||||
else
|
||||
id = stat->stat_type*multiplier + stat->stat_subtype;
|
||||
}
|
||||
|
||||
world.AddBonuses(values, id, stat->value, entity);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
@ -3122,7 +3187,6 @@ bool PlayerItemList::MoveItem(sint32 to_bag_id, int16 from_index, sint8 to, int8
|
|||
}
|
||||
}
|
||||
else{
|
||||
printf("7\n");
|
||||
MoveItem(item_from, item_to->details.bag_id, 0);
|
||||
MPlayerItems.releasewritelock(__FUNCTION__, __LINE__);
|
||||
return true;
|
||||
|
@ -3841,4 +3905,23 @@ string Item::CreateItemLink(int16 client_Version, bool bUseUniqueID) {
|
|||
ss << "\\aITEM " << details.item_id << ' ' << name << ':' << name << "\\/a";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int32 MasterItemList::GetItemStatIDByName(std::string name)
|
||||
{
|
||||
boost::to_lower(name);
|
||||
map<std::string, int32>::iterator itr = mappedItemStatsStrings.find(name.c_str());
|
||||
if(itr != mappedItemStatsStrings.end())
|
||||
return itr->second;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
std::string MasterItemList::GetItemStatNameByID(int32 id)
|
||||
{
|
||||
map<int32, std::string>::iterator itr = mappedItemStatTypeIDs.find(id);
|
||||
if(itr != mappedItemStatTypeIDs.end())
|
||||
return itr->second;
|
||||
|
||||
return std::string("");
|
||||
}
|
|
@ -347,6 +347,40 @@ extern MasterItemList master_item_list;
|
|||
#define ITEM_STAT_WIS 3
|
||||
#define ITEM_STAT_INT 4
|
||||
|
||||
#define ITEM_STAT_ADORNING 100
|
||||
#define ITEM_STAT_AGGRESSION 101
|
||||
#define ITEM_STAT_ARTIFICING 102
|
||||
#define ITEM_STAT_ARTISTRY 103
|
||||
#define ITEM_STAT_CHEMISTRY 104
|
||||
#define ITEM_STAT_CRUSHING 105
|
||||
#define ITEM_STAT_DEFENSE 106
|
||||
#define ITEM_STAT_DEFLECTION 107
|
||||
#define ITEM_STAT_DISRUPTION 108
|
||||
#define ITEM_STAT_FISHING 109
|
||||
#define ITEM_STAT_FLETCHING 110
|
||||
#define ITEM_STAT_FOCUS 111
|
||||
#define ITEM_STAT_FORESTING 112
|
||||
#define ITEM_STAT_GATHERING 113
|
||||
#define ITEM_STAT_METAL_SHAPING 114
|
||||
#define ITEM_STAT_METALWORKING 115
|
||||
#define ITEM_STAT_MINING 116
|
||||
#define ITEM_STAT_MINISTRATION 117
|
||||
#define ITEM_STAT_ORDINATION 118
|
||||
#define ITEM_STAT_PARRY 119
|
||||
#define ITEM_STAT_PIERCING 120
|
||||
#define ITEM_STAT_RANGED 121
|
||||
#define ITEM_STAT_SAFE_FALL 122
|
||||
#define ITEM_STAT_SCRIBING 123
|
||||
#define ITEM_STAT_SCULPTING 124
|
||||
#define ITEM_STAT_SLASHING 125
|
||||
#define ITEM_STAT_SUBJUGATION 126
|
||||
#define ITEM_STAT_SWIMMING 127
|
||||
#define ITEM_STAT_TAILORING 128
|
||||
#define ITEM_STAT_TINKERING 129
|
||||
#define ITEM_STAT_TRANSMUTING 130
|
||||
#define ITEM_STAT_TRAPPING 131
|
||||
#define ITEM_STAT_WEAPON_SKILLS 132
|
||||
|
||||
#define ITEM_STAT_VS_PHYSICAL 200
|
||||
#define ITEM_STAT_VS_HEAT 201 //elemental
|
||||
#define ITEM_STAT_VS_POISON 202 //noxious
|
||||
|
@ -932,6 +966,7 @@ public:
|
|||
};
|
||||
class MasterItemList{
|
||||
public:
|
||||
MasterItemList();
|
||||
~MasterItemList();
|
||||
map<int32,Item*> items;
|
||||
|
||||
|
@ -947,6 +982,11 @@ public:
|
|||
static int32 NextUniqueID();
|
||||
static void ResetUniqueID(int32 new_id);
|
||||
static int32 next_unique_id;
|
||||
int32 GetItemStatIDByName(std::string name);
|
||||
std::string GetItemStatNameByID(int32 id);
|
||||
void AddMappedItemStat(int32 id, std::string lower_case_name);
|
||||
map<std::string, int32> mappedItemStatsStrings;
|
||||
map<int32, std::string> mappedItemStatTypeIDs;
|
||||
};
|
||||
class PlayerItemList {
|
||||
public:
|
||||
|
|
|
@ -248,6 +248,40 @@ extern MasterItemList master_item_list;
|
|||
#define ITEM_STAT_WIS 3
|
||||
#define ITEM_STAT_INT 4
|
||||
|
||||
#define ITEM_STAT_ADORNING 100
|
||||
#define ITEM_STAT_AGGRESSION 101
|
||||
#define ITEM_STAT_ARTIFICING 102
|
||||
#define ITEM_STAT_ARTISTRY 103
|
||||
#define ITEM_STAT_CHEMISTRY 104
|
||||
#define ITEM_STAT_CRUSHING 105
|
||||
#define ITEM_STAT_DEFENSE 106
|
||||
#define ITEM_STAT_DEFLECTION 107
|
||||
#define ITEM_STAT_DISRUPTION 108
|
||||
#define ITEM_STAT_FISHING 109
|
||||
#define ITEM_STAT_FLETCHING 110
|
||||
#define ITEM_STAT_FOCUS 111
|
||||
#define ITEM_STAT_FORESTING 112
|
||||
#define ITEM_STAT_GATHERING 113
|
||||
#define ITEM_STAT_METAL_SHAPING 114
|
||||
#define ITEM_STAT_METALWORKING 115
|
||||
#define ITEM_STAT_MINING 116
|
||||
#define ITEM_STAT_MINISTRATION 117
|
||||
#define ITEM_STAT_ORDINATION 118
|
||||
#define ITEM_STAT_PARRY 119
|
||||
#define ITEM_STAT_PIERCING 120
|
||||
#define ITEM_STAT_RANGED 121
|
||||
#define ITEM_STAT_SAFE_FALL 122
|
||||
#define ITEM_STAT_SCRIBING 123
|
||||
#define ITEM_STAT_SCULPTING 124
|
||||
#define ITEM_STAT_SLASHING 125
|
||||
#define ITEM_STAT_SUBJUGATION 126
|
||||
#define ITEM_STAT_SWIMMING 127
|
||||
#define ITEM_STAT_TAILORING 128
|
||||
#define ITEM_STAT_TINKERING 129
|
||||
#define ITEM_STAT_TRANSMUTING 130
|
||||
#define ITEM_STAT_TRAPPING 131
|
||||
#define ITEM_STAT_WEAPON_SKILLS 132
|
||||
|
||||
#define ITEM_STAT_VS_PHYSICAL 200
|
||||
#define ITEM_STAT_VS_ELEMENTAL 201
|
||||
#define ITEM_STAT_VS_NOXIOUS 202
|
||||
|
|
|
@ -261,6 +261,40 @@ extern MasterItemList master_item_list;
|
|||
#define ITEM_STAT_WIS 3
|
||||
#define ITEM_STAT_INT 4
|
||||
|
||||
#define ITEM_STAT_ADORNING 100
|
||||
#define ITEM_STAT_AGGRESSION 101
|
||||
#define ITEM_STAT_ARTIFICING 102
|
||||
#define ITEM_STAT_ARTISTRY 103
|
||||
#define ITEM_STAT_CHEMISTRY 104
|
||||
#define ITEM_STAT_CRUSHING 105
|
||||
#define ITEM_STAT_DEFENSE 106
|
||||
#define ITEM_STAT_DEFLECTION 107
|
||||
#define ITEM_STAT_DISRUPTION 108
|
||||
#define ITEM_STAT_FISHING 109
|
||||
#define ITEM_STAT_FLETCHING 110
|
||||
#define ITEM_STAT_FOCUS 111
|
||||
#define ITEM_STAT_FORESTING 112
|
||||
#define ITEM_STAT_GATHERING 113
|
||||
#define ITEM_STAT_METAL_SHAPING 114
|
||||
#define ITEM_STAT_METALWORKING 115
|
||||
#define ITEM_STAT_MINING 116
|
||||
#define ITEM_STAT_MINISTRATION 117
|
||||
#define ITEM_STAT_ORDINATION 118
|
||||
#define ITEM_STAT_PARRY 119
|
||||
#define ITEM_STAT_PIERCING 120
|
||||
#define ITEM_STAT_RANGED 121
|
||||
#define ITEM_STAT_SAFE_FALL 122
|
||||
#define ITEM_STAT_SCRIBING 123
|
||||
#define ITEM_STAT_SCULPTING 124
|
||||
#define ITEM_STAT_SLASHING 125
|
||||
#define ITEM_STAT_SUBJUGATION 126
|
||||
#define ITEM_STAT_SWIMMING 127
|
||||
#define ITEM_STAT_TAILORING 128
|
||||
#define ITEM_STAT_TINKERING 129
|
||||
#define ITEM_STAT_TRANSMUTING 130
|
||||
#define ITEM_STAT_TRAPPING 131
|
||||
#define ITEM_STAT_WEAPON_SKILLS 132
|
||||
|
||||
#define ITEM_STAT_VS_PHYSICAL 200
|
||||
#define ITEM_STAT_VS_HEAT 201 //elemental
|
||||
#define ITEM_STAT_VS_POISON 202 //noxious
|
||||
|
|
|
@ -175,3 +175,37 @@
|
|||
#define TOV_ITEM_STAT_INT 4
|
||||
|
||||
|
||||
|
||||
#define TOV_ITEM_STAT_ADORNING 100
|
||||
#define TOV_ITEM_STAT_AGGRESSION 101
|
||||
#define TOV_ITEM_STAT_ARTIFICING 102
|
||||
#define TOV_ITEM_STAT_ARTISTRY 103
|
||||
#define TOV_ITEM_STAT_CHEMISTRY 104
|
||||
#define TOV_ITEM_STAT_CRUSHING 105
|
||||
#define TOV_ITEM_STAT_DEFENSE 106
|
||||
#define TOV_ITEM_STAT_DEFLECTION 107
|
||||
#define TOV_ITEM_STAT_DISRUPTION 108
|
||||
#define TOV_ITEM_STAT_FISHING 109
|
||||
#define TOV_ITEM_STAT_FLETCHING 110
|
||||
#define TOV_ITEM_STAT_FOCUS 111
|
||||
#define TOV_ITEM_STAT_FORESTING 112
|
||||
#define TOV_ITEM_STAT_GATHERING 113
|
||||
#define TOV_ITEM_STAT_METAL_SHAPING 114
|
||||
#define TOV_ITEM_STAT_METALWORKING 115
|
||||
#define TOV_ITEM_STAT_MINING 116
|
||||
#define TOV_ITEM_STAT_MINISTRATION 117
|
||||
#define TOV_ITEM_STAT_ORDINATION 118
|
||||
#define TOV_ITEM_STAT_PARRY 119
|
||||
#define TOV_ITEM_STAT_PIERCING 120
|
||||
#define TOV_ITEM_STAT_RANGED 121
|
||||
#define TOV_ITEM_STAT_SAFE_FALL 122
|
||||
#define TOV_ITEM_STAT_SCRIBING 123
|
||||
#define TOV_ITEM_STAT_SCULPTING 124
|
||||
#define TOV_ITEM_STAT_SLASHING 125
|
||||
#define TOV_ITEM_STAT_SUBJUGATION 126
|
||||
#define TOV_ITEM_STAT_SWIMMING 127
|
||||
#define TOV_ITEM_STAT_TAILORING 128
|
||||
#define TOV_ITEM_STAT_TINKERING 129
|
||||
#define TOV_ITEM_STAT_TRANSMUTING 130
|
||||
#define TOV_ITEM_STAT_TRAPPING 131
|
||||
#define TOV_ITEM_STAT_WEAPON_SKILLS 132
|
|
@ -2132,6 +2132,34 @@ int EQ2Emu_lua_AddSpawnSpellBonus(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_RemoveSpawnSpellBonus(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
LuaSpell* luaspell = lua_interface->GetCurrentSpell(state);
|
||||
|
||||
if (!spawn) {
|
||||
lua_interface->LogError("%s: LUA AddSpawnSpellBonus command error: spawn is not valid", lua_interface->GetScriptName(state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!spawn->IsEntity()) {
|
||||
lua_interface->LogError("%s: LUA AddSpawnSpellBonus command error: spawn is not an entity", lua_interface->GetScriptName(state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!luaspell || !luaspell->spell) {
|
||||
lua_interface->LogError("%s: LUA AddSpawnSpellBonus command error: can only be used in a spell script", lua_interface->GetScriptName(state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
((Entity*)spawn)->RemoveSpellBonus(luaspell);
|
||||
if (spawn->IsPlayer())
|
||||
((Player*)spawn)->SetCharSheetChanged(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_RemoveSpellBonus(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -7065,7 +7093,15 @@ int EQ2Emu_lua_CanHarvest(lua_State* state) {
|
|||
GroundSpawnEntry* entry = 0;
|
||||
bool can_harvest = false;
|
||||
sint32 min_skill = -1;
|
||||
|
||||
int16 totalSkill = skill->current_val;
|
||||
int32 skillID = master_item_list.GetItemStatIDByName(collection_skill);
|
||||
if(skillID != 0xFFFFFFFF)
|
||||
{
|
||||
((Entity*)player)->MStats.lock();
|
||||
totalSkill += ((Entity*)player)->stats[skillID];
|
||||
((Entity*)player)->MStats.unlock();
|
||||
}
|
||||
|
||||
// first, iterate through groundspawn_entries, discard tables player cannot use
|
||||
for (itr = groundspawn_entries->begin(); itr != groundspawn_entries->end(); itr++)
|
||||
{
|
||||
|
@ -7074,7 +7110,7 @@ int EQ2Emu_lua_CanHarvest(lua_State* state) {
|
|||
if (min_skill == -1 || entry->min_skill_level < min_skill)
|
||||
min_skill = entry->min_skill_level;
|
||||
// if player lacks skill, skip table
|
||||
if (entry->min_skill_level > skill->current_val)
|
||||
if (entry->min_skill_level > totalSkill)
|
||||
continue;
|
||||
// if bonus, but player lacks level, skip table
|
||||
if (entry->bonus_table && (player->GetLevel() < entry->min_adventure_level))
|
||||
|
@ -7103,7 +7139,7 @@ int EQ2Emu_lua_CanHarvest(lua_State* state) {
|
|||
msg.append("catch");
|
||||
|
||||
msg.append(" the %s. It requires %i %s skill, and your skill is %i.");
|
||||
client->Message(CHANNEL_HARVESTING_WARNINGS, msg.c_str(), ground->GetName(), min_skill, skill->name.data.c_str(), skill->current_val);
|
||||
client->Message(CHANNEL_HARVESTING_WARNINGS, msg.c_str(), ground->GetName(), min_skill, skill->name.data.c_str(), totalSkill);
|
||||
// You do not have enough skill to catch the band of fish. It requires 20 Fishing skill, and your skill is 12.
|
||||
}
|
||||
}
|
||||
|
@ -9984,12 +10020,16 @@ int EQ2Emu_lua_Evac(lua_State* state) {
|
|||
PacketStruct* packet = configReader.getStruct("WS_TeleportWithinZone", client->GetVersion());
|
||||
if (packet)
|
||||
{
|
||||
client->SetReloadingZone(true);
|
||||
packet->setDataByName("x", x);
|
||||
packet->setDataByName("y", y);
|
||||
packet->setDataByName("z", z);
|
||||
client->QueuePacket(packet->serialize());
|
||||
safe_delete(packet);
|
||||
}
|
||||
|
||||
client->GetCurrentZone()->ClearHate(client->GetPlayer());
|
||||
client->GetCurrentZone()->RemoveSpawn(client->GetPlayer(), false, false, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10807,6 +10847,7 @@ int EQ2Emu_lua_GetSpell(lua_State* state) {
|
|||
return 0;
|
||||
int32 spell_id = lua_interface->GetInt32Value(state);
|
||||
int8 spell_tier = lua_interface->GetInt8Value(state, 2);
|
||||
string custom_lua_script = lua_interface->GetStringValue(state, 3);
|
||||
if (spell_id > 0) {
|
||||
|
||||
if (spell_tier == 0)
|
||||
|
@ -10814,8 +10855,10 @@ int EQ2Emu_lua_GetSpell(lua_State* state) {
|
|||
|
||||
Spell* spell = master_spell_list.GetSpell(spell_id, spell_tier);
|
||||
LuaSpell* lua_spell = 0;
|
||||
if(custom_lua_script.size() < 1)
|
||||
custom_lua_script = spell->GetSpellData()->lua_script;
|
||||
if (lua_interface)
|
||||
lua_spell = lua_interface->GetSpell(spell->GetSpellData()->lua_script.c_str());
|
||||
lua_spell = lua_interface->GetSpell(custom_lua_script.c_str());
|
||||
|
||||
if (!lua_spell)
|
||||
return 0;
|
||||
|
@ -11793,5 +11836,49 @@ int EQ2Emu_lua_MakeRandomFloat(lua_State* state) {
|
|||
float max = lua_interface->GetFloatValue(state, 2);
|
||||
float result = MakeRandomFloat(min, max);
|
||||
lua_interface->SetFloatValue(state, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddIconValue(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
int32 value = lua_interface->GetInt32Value(state, 2);
|
||||
|
||||
lua_interface->ResetFunctionStack(state);
|
||||
|
||||
if(!spawn)
|
||||
{
|
||||
lua_interface->LogError("%s: LUA AddIconValue command error: spawn is not valid, does not exist", lua_interface->GetScriptName(state));
|
||||
lua_interface->SetBooleanValue(state, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spawn->AddIconValue(value);
|
||||
lua_interface->SetBooleanValue(state, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_RemoveIconValue(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
int32 value = lua_interface->GetInt32Value(state, 2);
|
||||
|
||||
lua_interface->ResetFunctionStack(state);
|
||||
|
||||
if(!spawn)
|
||||
{
|
||||
lua_interface->LogError("%s: LUA RemoveIconValue command error: spawn is not valid, does not exist", lua_interface->GetScriptName(state));
|
||||
lua_interface->SetBooleanValue(state, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spawn->RemoveIconValue(value);
|
||||
lua_interface->SetBooleanValue(state, true);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -409,6 +409,7 @@ int EQ2Emu_lua_RemoveThreatTransfer(lua_State* state);
|
|||
int EQ2Emu_lua_CureByType(lua_State* state);
|
||||
int EQ2Emu_lua_CureByControlEffect(lua_State* state);
|
||||
int EQ2Emu_lua_AddSpawnSpellBonus(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveSpawnSpellBonus(lua_State* state);
|
||||
int EQ2Emu_lua_CancelSpell(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveStealth(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveInvis(lua_State* state);
|
||||
|
@ -559,4 +560,7 @@ int EQ2Emu_lua_IsOpen(lua_State* state);
|
|||
|
||||
int EQ2Emu_lua_MakeRandomInt(lua_State* state);
|
||||
int EQ2Emu_lua_MakeRandomFloat(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_AddIconValue(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveIconValue(lua_State* state);
|
||||
#endif
|
|
@ -1124,6 +1124,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "CureByType", EQ2Emu_lua_CureByType);
|
||||
lua_register(state, "CureByControlEffect", EQ2Emu_lua_CureByControlEffect);
|
||||
lua_register(state, "AddSpawnSpellBonus", EQ2Emu_lua_AddSpawnSpellBonus);
|
||||
lua_register(state, "RemoveSpawnSpellBonus", EQ2Emu_lua_RemoveSpawnSpellBonus);
|
||||
lua_register(state, "CancelSpell", EQ2Emu_lua_CancelSpell);
|
||||
lua_register(state, "RemoveStealth", EQ2Emu_lua_RemoveStealth);
|
||||
lua_register(state, "RemoveInvis", EQ2Emu_lua_RemoveInvis);
|
||||
|
@ -1273,6 +1274,9 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
|
||||
lua_register(state, "MakeRandomInt", EQ2Emu_lua_MakeRandomInt);
|
||||
lua_register(state, "MakeRandomFloat", EQ2Emu_lua_MakeRandomFloat);
|
||||
|
||||
lua_register(state, "AddIconValue", EQ2Emu_lua_AddIconValue);
|
||||
lua_register(state, "RemoveIconValue", EQ2Emu_lua_RemoveIconValue);
|
||||
}
|
||||
|
||||
void LuaInterface::LogError(const char* error, ...) {
|
||||
|
|
|
@ -212,8 +212,10 @@ void Brain::AddHate(Entity* entity, sint32 hate) {
|
|||
else
|
||||
m_hatelist.insert(std::pair<int32, sint32>(entity->GetID(), hate));
|
||||
|
||||
entity->MHatedBy.lock();
|
||||
if (entity->HatedBy.count(m_body->GetID()) == 0)
|
||||
entity->HatedBy.insert(m_body->GetID());
|
||||
entity->MHatedBy.unlock();
|
||||
|
||||
// Unlock the list
|
||||
MHateList.releasewritelock(__FUNCTION__, __LINE__);
|
||||
|
@ -227,7 +229,11 @@ void Brain::ClearHate() {
|
|||
for (itr = m_hatelist.begin(); itr != m_hatelist.end(); itr++) {
|
||||
Spawn* spawn = m_body->GetZone()->GetSpawnByID(itr->first);
|
||||
if (spawn && spawn->IsEntity())
|
||||
((Entity*)spawn)->HatedBy.erase(itr->first);
|
||||
{
|
||||
((Entity*)spawn)->MHatedBy.lock();
|
||||
((Entity*)spawn)->HatedBy.erase(m_body->GetID());
|
||||
((Entity*)spawn)->MHatedBy.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the list
|
||||
|
@ -245,7 +251,9 @@ void Brain::ClearHate(Entity* entity) {
|
|||
// Erase the entity from the hate list
|
||||
m_hatelist.erase(entity->GetID());
|
||||
|
||||
entity->MHatedBy.lock();
|
||||
entity->HatedBy.erase(m_body->GetID());
|
||||
entity->MHatedBy.unlock();
|
||||
|
||||
// Unlock the hate list
|
||||
MHateList.releasewritelock(__FUNCTION__, __LINE__);
|
||||
|
|
|
@ -171,8 +171,6 @@ Player::~Player(){
|
|||
world.RemoveLottoPlayer(GetCharacterID());
|
||||
safe_delete(info);
|
||||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
player_spawn_index_map.clear();
|
||||
player_spawn_map.clear();
|
||||
player_spawn_reverse_id_map.clear();
|
||||
player_removed_spawns.clear();
|
||||
player_spawn_id_map.clear();
|
||||
|
@ -444,12 +442,8 @@ PacketStruct* PlayerInfo::serialize2(int16 version){
|
|||
else
|
||||
packet->setDataByName("house_zone", "None");
|
||||
//packet->setDataByName("account_age_base", 14);
|
||||
if(player->GetHPRegen() == 0)
|
||||
player->SetHPRegen((int)(info_struct->get_level()*.75)+(int)(info_struct->get_level()/10)+3);
|
||||
if(player->GetPowerRegen() == 0)
|
||||
player->SetPowerRegen(info_struct->get_level()+(int)(info_struct->get_level()/10)+4);
|
||||
packet->setDataByName("hp_regen", player->GetHPRegen());
|
||||
packet->setDataByName("power_regen", player->GetPowerRegen());
|
||||
packet->setDataByName("hp_regen", info_struct->get_hp_regen());
|
||||
packet->setDataByName("power_regen", info_struct->get_power_regen());
|
||||
/*packet->setDataByName("unknown11", -1, 0);
|
||||
packet->setDataByName("unknown11", -1, 1);
|
||||
packet->setDataByName("unknown13", 201, 0);
|
||||
|
@ -677,12 +671,9 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
packet->setDataByName("base_power", player->GetTotalPowerBase());
|
||||
packet->setDataByName("conc_used", info_struct->get_cur_concentration());
|
||||
packet->setDataByName("conc_max", info_struct->get_max_concentration());
|
||||
if (player->GetHPRegen() == 0)
|
||||
player->SetHPRegen((int)(info_struct->get_level() * .75) + (int)(info_struct->get_level() / 10) + 1);
|
||||
if (player->GetPowerRegen() == 0)
|
||||
player->SetPowerRegen(info_struct->get_level() + (int)(info_struct->get_level() / 10) + 4);
|
||||
packet->setDataByName("hp_regen", player->GetHPRegen() + player->stats[ITEM_STAT_HPREGEN]);
|
||||
packet->setDataByName("power_regen", player->GetPowerRegen() + player->stats[ITEM_STAT_MANAREGEN]);
|
||||
packet->setDataByName("hp_regen", player->GetInfoStruct()->get_hp_regen());
|
||||
packet->setDataByName("power_regen", player->GetInfoStruct()->get_power_regen());
|
||||
|
||||
// packet->setDataByName("unknown_1_4a_MJ", 96); //-1// was unknown11
|
||||
// packet->setDataByName("unknown_1_4b_MJ", 96); //-1
|
||||
packet->setDataByName("stat_bonus_health", player->CalculateBonusMod());//bonus health and bonus power getting same value?
|
||||
|
@ -697,15 +688,19 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
packet->setDataByName("mitigation_pct_pvp", 559); // % calculation Mitigation % vs PvP 559 = 55.9%// confirmed DoV
|
||||
packet->setDataByName("toughness", 0);//toughness// confirmed DoV
|
||||
packet->setDataByName("toughness_resist_dmg_pvp", 0);//toughness_resist_dmg_pvp 73 = 7300% // confirmed DoV
|
||||
packet->setDataByName("avoidance_pct", 0);//avoidance_pct 192 = 19.2% // confirmed DoV
|
||||
packet->setDataByName("avoidance_base", info_struct->get_avoidance_base()); // confirmed DoV
|
||||
packet->setDataByName("avoidance_pct", (int16)info_struct->get_avoidance_display()*10.0f);//avoidance_pct 192 = 19.2% // confirmed DoV
|
||||
packet->setDataByName("avoidance_base", (int16)info_struct->get_avoidance_base()*10.0f); // confirmed DoV
|
||||
packet->setDataByName("avoidance", info_struct->get_cur_avoidance());
|
||||
// packet->setDataByName("unknown_1096_1_MJ", 90);//unknown_1096_1_MJ
|
||||
packet->setDataByName("base_avoidance_pct", info_struct->get_base_avoidance_pct());// confirmed DoV
|
||||
// packet->setDataByName("unknown_1096_2_MJ", 89);//unknown_1096_2_MJ
|
||||
packet->setDataByName("parry", info_struct->get_parry_base());// confirmed DoV
|
||||
float parry_pct = info_struct->get_parry(); // client works off of int16, but we use floats to track the actual x/100%
|
||||
packet->setDataByName("parry",(int16)(parry_pct*10.0f));// confirmed DoV
|
||||
// packet->setDataByName("unknown_1096_3_MJ", 88);//unknown_1096_3_MJ
|
||||
packet->setDataByName("block", info_struct->get_block_base());// confirmed DoV
|
||||
|
||||
float block_pct = info_struct->get_block()*10.0f;
|
||||
|
||||
packet->setDataByName("block", (int16)block_pct);// confirmed DoV
|
||||
// packet->setDataByName("unknown_1096_4_MJ", 87);//unknown_1096_4_MJ
|
||||
packet->setDataByName("uncontested_block", info_struct->get_uncontested_block());// confirmed DoV
|
||||
// packet->setDataByName("unknown_1096_5_MJ", 86);//unknown_1096_5_MJ
|
||||
|
@ -895,7 +890,9 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
packet->setDataByName("crit_chance", info_struct->get_crit_chance());// dov confirmed
|
||||
//unknown_1096_32_MJ
|
||||
packet->setDataByName("crit_bonus", info_struct->get_crit_bonus());// dov confirmed
|
||||
((Entity*)player)->MStats.lock();
|
||||
packet->setDataByName("potency", player->stats[ITEM_STAT_POTENCY]);//info_struct->get_potency);// dov confirmed
|
||||
((Entity*)player)->MStats.unlock();
|
||||
//unknown_1096_33_MJ
|
||||
packet->setDataByName("reuse_speed", info_struct->get_reuse_speed());// dov confirmed
|
||||
packet->setDataByName("recovery_speed", info_struct->get_recovery_speed());// dov confirmed
|
||||
|
@ -910,12 +907,14 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
//unknown_1096_37_MJ
|
||||
//toughness_resist_crit_pvp
|
||||
//unknown_1096_38_MJ
|
||||
((Entity*)player)->MStats.lock();
|
||||
packet->setDataByName("durability_mod", player->stats[ITEM_STAT_DURABILITY_MOD]);// dov confirmed
|
||||
packet->setDataByName("durability_add", player->stats[ITEM_STAT_DURABILITY_ADD]);// dov confirmed
|
||||
packet->setDataByName("progress_mod", player->stats[ITEM_STAT_PROGRESS_MOD]);// dov confirmed
|
||||
packet->setDataByName("progress_add", player->stats[ITEM_STAT_PROGRESS_ADD]);// dov confirmed
|
||||
packet->setDataByName("success_mod", player->stats[ITEM_STAT_SUCCESS_MOD]);// dov confirmed
|
||||
packet->setDataByName("crit_success_mod", player->stats[ITEM_STAT_CRIT_SUCCESS_MOD]);// dov confirmed
|
||||
((Entity*)player)->MStats.unlock();
|
||||
|
||||
//unknown_1096_39_MJ
|
||||
/////GRoup Members
|
||||
|
@ -966,6 +965,7 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
|
||||
|
||||
|
||||
((Entity*)player)->MStats.lock();
|
||||
packet->setDataByName("rare_harvest_chance", player->stats[ITEM_STAT_RARE_HARVEST_CHANCE]);
|
||||
packet->setDataByName("max_crafting", player->stats[ITEM_STAT_MAX_CRAFTING]);
|
||||
packet->setDataByName("component_refund", player->stats[ITEM_STAT_COMPONENT_REFUND]);
|
||||
|
@ -976,6 +976,7 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
packet->setDataByName("ex_progress_mod", player->stats[ITEM_STAT_EX_PROGRESS_MOD]);
|
||||
packet->setDataByName("ex_progress_add", player->stats[ITEM_STAT_EX_PROGRESS_ADD]);
|
||||
packet->setDataByName("ex_success_mod", player->stats[ITEM_STAT_EX_SUCCESS_MOD]);
|
||||
((Entity*)player)->MStats.unlock();
|
||||
|
||||
packet->setDataByName("flurry", info_struct->get_flurry());
|
||||
packet->setDataByName("unknown153", 153);
|
||||
|
@ -3010,8 +3011,6 @@ SpellEffects* Player::GetSpellEffects() {
|
|||
void Player::ClearEverything(){
|
||||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
player_removed_spawns.clear();
|
||||
player_spawn_map.clear();
|
||||
player_spawn_index_map.clear();
|
||||
player_spawn_id_map.clear();
|
||||
player_spawn_reverse_id_map.clear();
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
|
@ -3524,13 +3523,22 @@ void Player::InCombat(bool val, bool range) {
|
|||
else
|
||||
GetInfoStruct()->set_flags(GetInfoStruct()->get_flags() & ~(1 << (range?CF_RANGED_AUTO_ATTACK:CF_AUTO_ATTACK)));
|
||||
|
||||
bool changeCombatState = false;
|
||||
|
||||
if((in_combat && !val) || (!in_combat && val))
|
||||
changeCombatState = true;
|
||||
|
||||
in_combat = val;
|
||||
if(in_combat)
|
||||
AddIconValue(64);
|
||||
else
|
||||
RemoveIconValue(64);
|
||||
|
||||
if(changeCombatState)
|
||||
SetRegenValues(GetInfoStruct()->get_effective_level());
|
||||
|
||||
charsheet_changed = true;
|
||||
info_changed = true;
|
||||
}
|
||||
|
||||
void Player::SetCharSheetChanged(bool val){
|
||||
|
@ -3821,7 +3829,9 @@ int32 Player::GetTSXP() {
|
|||
}
|
||||
|
||||
bool Player::AddXP(int32 xp_amount){
|
||||
MStats.lock();
|
||||
xp_amount += ((xp_amount) * stats[ITEM_STAT_COMBATEXPMOD]) / 100;
|
||||
MStats.unlock();
|
||||
|
||||
float current_xp_percent = ((float)GetXP()/(float)GetNeededXP())*100;
|
||||
float miniding_min_percent = ((int)(current_xp_percent/10)+1)*10;
|
||||
|
@ -3845,7 +3855,9 @@ bool Player::AddXP(int32 xp_amount){
|
|||
}
|
||||
|
||||
bool Player::AddTSXP(int32 xp_amount){
|
||||
MStats.lock();
|
||||
xp_amount += ((xp_amount)*stats[ITEM_STAT_TRADESKILLEXPMOD]) / 100;
|
||||
MStats.unlock();
|
||||
|
||||
float current_xp_percent = ((float)GetTSXP()/(float)GetNeededTSXP())*100;
|
||||
float miniding_min_percent = ((int)(current_xp_percent/10)+1)*10;
|
||||
|
@ -3901,8 +3913,8 @@ Spawn* Player::GetSpawnByIndex(int16 index){
|
|||
Spawn* spawn = 0;
|
||||
|
||||
index_mutex.readlock(__FUNCTION__, __LINE__);
|
||||
if(player_spawn_map.count(index) > 0)
|
||||
spawn = player_spawn_map[index];
|
||||
if(player_spawn_id_map.count(index) > 0)
|
||||
spawn = player_spawn_id_map[index];
|
||||
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
return spawn;
|
||||
|
@ -3912,8 +3924,8 @@ int16 Player::GetIndexForSpawn(Spawn* spawn) {
|
|||
int16 val = 0;
|
||||
|
||||
index_mutex.readlock(__FUNCTION__, __LINE__);
|
||||
if(player_spawn_index_map.count(spawn) > 0)
|
||||
val = player_spawn_index_map[spawn];
|
||||
if(player_spawn_reverse_id_map.count(spawn) > 0)
|
||||
val = player_spawn_reverse_id_map[spawn];
|
||||
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
return val;
|
||||
|
@ -3942,11 +3954,11 @@ void Player::RemoveSpawn(Spawn* spawn)
|
|||
|
||||
player_removed_spawns[spawn] = 1;
|
||||
|
||||
if (player_spawn_index_map[spawn] && player_spawn_map.count(player_spawn_index_map[spawn]) > 0)
|
||||
player_spawn_map.erase(player_spawn_index_map[spawn]);
|
||||
if (player_spawn_reverse_id_map[spawn] && player_spawn_id_map.count(player_spawn_reverse_id_map[spawn]) > 0)
|
||||
player_spawn_id_map.erase(player_spawn_reverse_id_map[spawn]);
|
||||
|
||||
if (player_spawn_index_map.count(spawn) > 0)
|
||||
player_spawn_index_map.erase(spawn);
|
||||
if (player_spawn_reverse_id_map.count(spawn) > 0)
|
||||
player_spawn_reverse_id_map.erase(spawn);
|
||||
|
||||
if (player_spawn_id_map.count(spawn->GetID()) && player_spawn_id_map[spawn->GetID()] == spawn)
|
||||
player_spawn_id_map.erase(spawn->GetID());
|
||||
|
@ -5019,8 +5031,11 @@ PlayerItemList* Player::GetPlayerItemList(){
|
|||
return &item_list;
|
||||
}
|
||||
|
||||
void Player::ResetSavedSpawns(){
|
||||
void Player::ResetRemovedSpawns(){
|
||||
player_removed_spawns.clear();
|
||||
}
|
||||
void Player::ResetSavedSpawns(){
|
||||
ResetRemovedSpawns();
|
||||
|
||||
vis_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
spawn_vis_packet_list.clear();
|
||||
|
@ -5037,8 +5052,6 @@ void Player::ResetSavedSpawns(){
|
|||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
player_spawn_reverse_id_map.clear();
|
||||
player_spawn_id_map.clear();
|
||||
player_spawn_map.clear();
|
||||
player_spawn_index_map.clear();
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
|
||||
m_playerSpawnQuestsRequired.writelock(__FUNCTION__, __LINE__);
|
||||
|
@ -5116,7 +5129,10 @@ bool Player::CheckLevelStatus(int16 new_level) {
|
|||
Skill* Player::GetSkillByName(const char* name, bool check_update){
|
||||
Skill* ret = skill_list.GetSkillByName(name);
|
||||
if(check_update)
|
||||
skill_list.CheckSkillIncrease(ret);
|
||||
{
|
||||
if(skill_list.CheckSkillIncrease(ret))
|
||||
CalculateBonuses();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -5793,7 +5809,6 @@ void Player::InitXPTable() {
|
|||
void Player::SendQuestRequiredSpawns(int32 quest_id){
|
||||
bool locked = true;
|
||||
m_playerSpawnQuestsRequired.readlock(__FUNCTION__, __LINE__);
|
||||
Quest* quest = GetQuest(quest_id);
|
||||
if (player_spawn_quests_required.size() > 0 ) {
|
||||
ZoneServer* zone = GetZone();
|
||||
Client* client = zone->GetClientBySpawn(this);
|
||||
|
@ -6122,4 +6137,22 @@ void Player::UpdateTargetInvisHistory(int32 targetID, bool canSeeStatus)
|
|||
void Player::RemoveTargetInvisHistory(int32 targetID)
|
||||
{
|
||||
target_invis_history.erase(targetID);
|
||||
}
|
||||
|
||||
void Player::SetSpawnMap(Spawn* spawn)
|
||||
{
|
||||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
spawn_id += 1;
|
||||
if (spawn_index == 255)
|
||||
spawn_index += 1; //just so we dont have to worry about overloading
|
||||
|
||||
int32 tmp_id = spawn_id;
|
||||
|
||||
player_spawn_id_map[tmp_id] = spawn;
|
||||
|
||||
if(player_spawn_reverse_id_map.count(spawn))
|
||||
player_spawn_reverse_id_map.erase(spawn);
|
||||
|
||||
player_spawn_reverse_id_map.insert(make_pair(spawn,tmp_id));
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
|
@ -599,30 +599,19 @@ public:
|
|||
if (player_spawn_reverse_id_map.count(spawn) > 0)
|
||||
id = player_spawn_reverse_id_map[spawn];
|
||||
index_mutex.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void SetSpawnMap(Spawn* spawn)
|
||||
void SetSpawnMap(Spawn* spawn);
|
||||
|
||||
void SetSpawnMapIndex(Spawn* spawn, int32 index)
|
||||
{
|
||||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
spawn_id += 1;
|
||||
int32 tmp_id = spawn_id;
|
||||
player_spawn_id_map[tmp_id] = spawn;
|
||||
|
||||
if(player_spawn_reverse_id_map.count(spawn))
|
||||
player_spawn_reverse_id_map.erase(spawn);
|
||||
|
||||
player_spawn_reverse_id_map.insert(make_pair(spawn,tmp_id));
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
void SetSpawnMapIndex(Spawn* spawn, int16 index)
|
||||
{
|
||||
index_mutex.writelock(__FUNCTION__, __LINE__);
|
||||
if (player_spawn_map.count(index))
|
||||
player_spawn_map[index] = spawn;
|
||||
if (player_spawn_id_map.count(index))
|
||||
player_spawn_id_map[index] = spawn;
|
||||
else
|
||||
player_spawn_map[index] = spawn;
|
||||
player_spawn_id_map[index] = spawn;
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
|
@ -636,16 +625,8 @@ public:
|
|||
|
||||
new_index = spawn_index;
|
||||
|
||||
if (player_spawn_index_map.count(spawn))
|
||||
player_spawn_index_map.erase(spawn);
|
||||
|
||||
player_spawn_index_map.insert(make_pair(spawn,new_index));
|
||||
|
||||
if (player_spawn_map.count(new_index))
|
||||
player_spawn_map[new_index] = spawn;
|
||||
else
|
||||
player_spawn_map.insert(make_pair(new_index, spawn));
|
||||
|
||||
player_spawn_id_map[new_index] = spawn;
|
||||
player_spawn_reverse_id_map[spawn] = new_index;
|
||||
index_mutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
|
||||
return new_index;
|
||||
|
@ -711,7 +692,7 @@ public:
|
|||
void SetGroupInformation(PacketStruct* packet);
|
||||
|
||||
|
||||
|
||||
void ResetRemovedSpawns();
|
||||
void ResetSavedSpawns();
|
||||
bool IsReturningFromLD();
|
||||
void SetReturningFromLD(bool val);
|
||||
|
@ -960,6 +941,20 @@ public:
|
|||
bool HasGMVision() { return gm_vision; }
|
||||
void SetGMVision(bool val) { gm_vision = val; }
|
||||
|
||||
void StopCombat(int8 type=0) {
|
||||
switch(type)
|
||||
{
|
||||
case 2:
|
||||
SetRangeAttack(false);
|
||||
InCombat(false, true);
|
||||
break;
|
||||
default:
|
||||
InCombat(false);
|
||||
InCombat(false, true);
|
||||
SetRangeAttack(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1092,8 +1087,6 @@ private:
|
|||
|
||||
bool gm_vision;
|
||||
|
||||
map<Spawn*, int16> player_spawn_index_map;
|
||||
map<int16, Spawn*> player_spawn_map;
|
||||
map<int32, Spawn*> player_spawn_id_map;
|
||||
map<Spawn*, int32> player_spawn_reverse_id_map;
|
||||
map<Spawn*, int8> player_removed_spawns;
|
||||
|
|
|
@ -220,7 +220,7 @@ void RuleManager::Init()
|
|||
RULE_INIT(R_Combat, MaxCombatRange, "4.0");
|
||||
/* SPAWN */
|
||||
RULE_INIT(R_Spawn, SpeedMultiplier, "300"); // note: this value was 1280 until 6/1/2009, then was 600 til Sep 2009, when it became 300...?
|
||||
//RULE_INIT(R_Spawn, SpeedRatio, "0"); // was 1280/7.5 and 600/7.5 until it became 300.
|
||||
RULE_INIT(R_Spawn, ClassicRegen, "0");
|
||||
|
||||
/* TIMER */
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ enum RuleType {
|
|||
|
||||
/* SPAWN */
|
||||
SpeedMultiplier,
|
||||
ClassicRegen,
|
||||
//SpeedRatio,
|
||||
|
||||
/* UI */
|
||||
|
|
|
@ -3950,3 +3950,40 @@ int32 Spawn::GetRegionType(Region_Node* inNode, ZBSP_Node* rootNode)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
float Spawn::SpawnAngle(Spawn* target, float selfx, float selfz)
|
||||
{
|
||||
if (!target || target == this)
|
||||
return 0.0f;
|
||||
|
||||
float angle, lengthb, vectorx, vectorz, dotp;
|
||||
float spx = (target->GetX()); // mob xloc (inverse because eq)
|
||||
float spz = -(target->GetZ()); // mob yloc
|
||||
float heading = target->GetHeading(); // mob heading
|
||||
if (heading < 270)
|
||||
heading += 90;
|
||||
else
|
||||
heading -= 270;
|
||||
|
||||
heading = heading * 3.1415f / 180.0f; // convert to radians
|
||||
vectorx = spx + (10.0f * std::cos(heading)); // create a vector based on heading
|
||||
vectorz = spz + (10.0f * std::sin(heading)); // of spawn length 10
|
||||
|
||||
// length of spawn to player vector
|
||||
lengthb = (float) std::sqrt(((selfx - spx) * (selfx - spx)) + ((-selfz - spz) * (-selfz - spz)));
|
||||
|
||||
// calculate dot product to get angle
|
||||
// Handle acos domain errors due to floating point rounding errors
|
||||
dotp = ((vectorx - spx) * (selfx - spx) +
|
||||
(vectorz - spz) * (-selfz - spz)) / (10.0f * lengthb);
|
||||
|
||||
if (dotp > 1)
|
||||
return 0.0f;
|
||||
else if (dotp < -1)
|
||||
return 180.0f;
|
||||
|
||||
angle = std::acos(dotp);
|
||||
angle = angle * 180.0f / 3.1415f;
|
||||
|
||||
return angle;
|
||||
}
|
|
@ -1194,6 +1194,14 @@ public:
|
|||
bool InRegion(Region_Node* inNode, ZBSP_Node* rootNode);
|
||||
int32 GetRegionType(Region_Node* inNode, ZBSP_Node* rootNode);
|
||||
|
||||
float SpawnAngle(Spawn* target, float selfx, float selfz);
|
||||
bool BehindSpawn(Spawn *target, float selfx, float selfz)
|
||||
{ return (!target || target == this) ? false : SpawnAngle(target, selfx, selfz) > 90.0f; }
|
||||
bool InFrontSpawn(Spawn *target, float selfx, float selfz)
|
||||
{ return (!target || target == this) ? false : SpawnAngle(target, selfx, selfz) < 63.0f; }
|
||||
bool IsFlankingSpawn(Spawn *target, float selfx, float selfz)
|
||||
{ return (!target || target == this) ? false : SpawnAngle(target, selfx, selfz) > 63.0f; }
|
||||
|
||||
std::map<std::map<Region_Node*, ZBSP_Node*>, Region_Status> Regions;
|
||||
Mutex RegionMutex;
|
||||
protected:
|
||||
|
|
|
@ -102,8 +102,10 @@ void TradeskillMgr::Process() {
|
|||
float crit_fail = m_critFail;
|
||||
|
||||
// Modify the % chance for success based off of stats
|
||||
client->GetPlayer()->MStats.lock();
|
||||
fail -= client->GetPlayer()->stats[ITEM_STAT_SUCCESS_MOD];
|
||||
success += client->GetPlayer()->stats[ITEM_STAT_SUCCESS_MOD];
|
||||
client->GetPlayer()->MStats.unlock();
|
||||
|
||||
// add values together for the if
|
||||
crit_success += crit_fail;
|
||||
|
@ -157,8 +159,10 @@ void TradeskillMgr::Process() {
|
|||
}
|
||||
|
||||
// Modify the progress/durability by the players stats
|
||||
client->GetPlayer()->MStats.lock();
|
||||
progress += client->GetPlayer()->stats[ITEM_STAT_PROGRESS_ADD];
|
||||
durability += client->GetPlayer()->stats[ITEM_STAT_DURABILITY_ADD];
|
||||
client->GetPlayer()->MStats.unlock();
|
||||
|
||||
tradeskill->currentDurability += durability;
|
||||
tradeskill->currentProgress += progress;
|
||||
|
|
|
@ -430,9 +430,9 @@ void RegionMapV1::TicRegionsNearSpawn(Spawn *spawn, Client *client) const
|
|||
node->dist, node->x, node->y, node->z, node->regionScriptName.c_str());
|
||||
WaterRegionType whatWasRegionType = RegionTypeNormal; // default will be 0
|
||||
|
||||
if (BSP_Root->special == -3)
|
||||
if (BSP_Root->special == SPECIAL_REGION_LAVA_OR_DEATH)
|
||||
whatWasRegionType = RegionTypeLava; // 2
|
||||
else if (BSP_Root->special == 1)
|
||||
else if (BSP_Root->special == SPECIAL_REGION_WATER)
|
||||
whatWasRegionType = RegionTypeWater; // 1
|
||||
|
||||
int32 returnValue = 0;
|
||||
|
@ -652,10 +652,10 @@ WaterRegionType RegionMapV1::BSPReturnRegionWaterRegion(const Region_Node* regio
|
|||
else if (current_node->left == -2) {
|
||||
switch(current_node->special)
|
||||
{
|
||||
case -3:
|
||||
case SPECIAL_REGION_LAVA_OR_DEATH:
|
||||
return(RegionTypeLava);
|
||||
break;
|
||||
case 1:
|
||||
case SPECIAL_REGION_WATER:
|
||||
return(RegionTypeWater);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
class Client;
|
||||
class Spawn;
|
||||
|
||||
#define SPECIAL_REGION_LAVA_OR_DEATH 4294967293
|
||||
#define SPECIAL_REGION_WATER 1
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct ZBSP_Node {
|
||||
int32 node_number;
|
||||
|
|
|
@ -198,6 +198,7 @@ Client::Client(EQStream* ieqs) : pos_update(125), quest_pos_timer(2000), lua_deb
|
|||
rejoin_group_id = 0;
|
||||
lastRegionRemapTime = 0;
|
||||
regionDebugMessaging = false;
|
||||
client_reloading_zone = false;
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
|
@ -632,7 +633,13 @@ void Client::HandlePlayerRevive(int32 point_id)
|
|||
void Client::SendCharInfo() {
|
||||
EQ2Packet* app;
|
||||
|
||||
if(IsReloadingZone())
|
||||
{
|
||||
GetPlayer()->ResetRemovedSpawns();
|
||||
SetReloadingZone(false);
|
||||
}
|
||||
|
||||
|
||||
player->SetEquippedItemAppearances();
|
||||
|
||||
ClientPacketFunctions::SendCharacterData(this);
|
||||
|
@ -663,7 +670,7 @@ void Client::SendCharInfo() {
|
|||
ClientPacketFunctions::SendAbilities(this);
|
||||
|
||||
ClientPacketFunctions::SendSkillBook(this);
|
||||
if (!player->IsResurrecting()) {
|
||||
if (!IsReloadingZone() && !player->IsResurrecting()) {
|
||||
if(GetVersion() > 546) //we will send this later on for 546 and below
|
||||
ClientPacketFunctions::SendUpdateSpellBook(this);
|
||||
}
|
||||
|
@ -673,7 +680,7 @@ void Client::SendCharInfo() {
|
|||
ClientPacketFunctions::SendLoginCommandMessages(this);
|
||||
|
||||
GetCurrentZone()->AddSpawn(player);
|
||||
|
||||
|
||||
//SendCollectionList();
|
||||
Guild* guild = player->GetGuild();
|
||||
if (guild)
|
||||
|
@ -1420,8 +1427,11 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
}*/
|
||||
float safe_height = 13.0f;
|
||||
Skill* skill = GetPlayer()->GetSkillByName("Safe Fall", true);
|
||||
GetPlayer()->MStats.lock();
|
||||
float deflectionStat = GetPlayer()->stats[ITEM_STAT_SAFE_FALL];
|
||||
GetPlayer()->MStats.unlock();
|
||||
if (skill)
|
||||
safe_height += (skill->current_val + 1) / 5;
|
||||
safe_height += (skill->current_val + 1 + deflectionStat) / 5;
|
||||
|
||||
if (height > safe_height) {
|
||||
int16 damage = (int16)ceil((height - safe_height) * 125);
|
||||
|
@ -4210,8 +4220,6 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
info->set_magic_base((int16)(new_level * 1.5 + 10));
|
||||
info->set_divine_base((int16)(new_level * 1.5 + 10));
|
||||
info->set_poison_base((int16)(new_level * 1.5 + 10));
|
||||
GetPlayer()->SetHPRegen((int)(new_level * .75) + (int)(new_level / 10) + 3);
|
||||
GetPlayer()->SetPowerRegen(new_level + (int)(new_level / 10) + 4);
|
||||
GetPlayer()->GetInfoStruct()->set_poison_base((int16)(new_level * 1.5 + 10));
|
||||
UpdateTimeStampFlag(LEVEL_UPDATE_FLAG);
|
||||
GetPlayer()->SetCharSheetChanged(true);
|
||||
|
@ -8283,7 +8291,7 @@ void Client::InspectPlayer(Player* player_to_inspect) {
|
|||
packet->setDataByName("power_base", player_to_inspect->GetTotalPowerBase());
|
||||
packet->setDataByName("mitigation", 0);
|
||||
packet->setDataByName("unknown1", 0);
|
||||
packet->setDataByName("avoidance", 0);
|
||||
packet->setDataByName("avoidance", player_to_inspect->GetInfoStruct()->get_cur_avoidance());
|
||||
packet->setDataByName("unknown2", 0);
|
||||
packet->setDataByName("mitigation_percentage", 0);
|
||||
packet->setDataByName("strength", player_to_inspect->GetStr());
|
||||
|
|
|
@ -467,6 +467,9 @@ public:
|
|||
int8 mailType, int32 copper, int32 silver, int32 gold, int32 platinum, int32 item_id, int16 stack_size, int32 time_sent, int32 expire_time);
|
||||
|
||||
void SendEquipOrInvUpdateBySlot(int8 slot);
|
||||
|
||||
void SetReloadingZone(bool val) { client_reloading_zone = val; }
|
||||
bool IsReloadingZone() { return client_reloading_zone; }
|
||||
private:
|
||||
void SavePlayerImages();
|
||||
void SkillChanged(Skill* skill, int16 previous_value, int16 new_value);
|
||||
|
@ -576,6 +579,8 @@ private:
|
|||
int32 lastRegionRemapTime;
|
||||
|
||||
bool regionDebugMessaging;
|
||||
|
||||
bool client_reloading_zone;
|
||||
};
|
||||
|
||||
class ClientList {
|
||||
|
|
|
@ -96,6 +96,8 @@ extern int errno;
|
|||
// extern volatile bool RunLoops; // never used in the zone server?
|
||||
// extern Classes classes; // never used in the zone server?
|
||||
|
||||
#define NO_CATCH 1
|
||||
|
||||
extern WorldDatabase database;
|
||||
extern sint32 numzones;
|
||||
extern ClientList client_list;
|
||||
|
@ -1821,7 +1823,7 @@ void ZoneServer::ProcessDrowning(){
|
|||
Client* client = itr->first;
|
||||
Player* player = client->GetPlayer();
|
||||
drowning_victims.Get(client) = Timer::GetCurrentTime2() + 2000;
|
||||
damage = player->GetTotalHP()/20 + player->GetHPRegen();
|
||||
damage = player->GetTotalHP()/20 + player->GetInfoStruct()->get_hp_regen();
|
||||
player->TakeDamage(damage);
|
||||
if(player->GetHP() == 0)
|
||||
dead_list.push_back(client);
|
||||
|
@ -3780,7 +3782,7 @@ void ZoneServer::RemoveFromRangeMap(Client* client){
|
|||
}
|
||||
*/
|
||||
|
||||
void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool lock)
|
||||
void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool lock, bool erase_from_spawn_list)
|
||||
{
|
||||
LogWrite(ZONE__DEBUG, 3, "Zone", "Processing RemoveSpawn function for %s (%i)...", spawn->GetName(),spawn->GetID());
|
||||
|
||||
|
@ -3807,7 +3809,8 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
|
|||
spawn_expire_timers.erase(spawn->GetID());
|
||||
|
||||
// we will remove the spawn ptr and entry in the spawn_list later.. it is not safe right now (lua? client process? spawn process? etc? too many factors)
|
||||
AddPendingSpawnRemove(spawn->GetID());
|
||||
if(erase_from_spawn_list)
|
||||
AddPendingSpawnRemove(spawn->GetID());
|
||||
|
||||
PacketStruct* packet = 0;
|
||||
int16 packet_version = 0;
|
||||
|
@ -4172,7 +4175,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
|
|||
|
||||
// Remove hate towards dead from all npc's in the zone
|
||||
ClearHate((Entity*)dead);
|
||||
|
||||
|
||||
// Check kill and death procs
|
||||
if (killer && dead != killer){
|
||||
if (dead->IsEntity())
|
||||
|
@ -4525,6 +4528,7 @@ void ZoneServer::SendDamagePacket(Spawn* attacker, Spawn* victim, int8 type1, in
|
|||
packet->setArrayDataByName("damage_type", damage_type);
|
||||
packet->setArrayDataByName("damage", damage);
|
||||
}
|
||||
|
||||
if (!attacker)
|
||||
packet->setSubstructDataByName("header", "attacker", 0xFFFFFFFF);
|
||||
else
|
||||
|
@ -4796,6 +4800,11 @@ void ZoneServer::SendZoneSpawns(Client* client){
|
|||
for (itr = spawn_list.begin(); itr != spawn_list.end(); itr++) {
|
||||
Spawn* spawn = itr->second;
|
||||
if (spawn) {
|
||||
if(spawn == client->GetPlayer() && client->IsReloadingZone())
|
||||
{
|
||||
client->GetPlayer()->SetSpawnMap(spawn);
|
||||
}
|
||||
|
||||
CheckSpawnRange(client, spawn, true);
|
||||
}
|
||||
}
|
||||
|
@ -6508,8 +6517,10 @@ void ZoneServer::ResurrectSpawn(Spawn* spawn, Client* client) {
|
|||
|
||||
if(!no_calcs && caster){
|
||||
//Potency Mod
|
||||
((Entity*)caster)->MStats.lock();
|
||||
heal_amt *= ((caster->stats[ITEM_STAT_POTENCY] / 100) + 1);
|
||||
power_amt *= ((caster->stats[ITEM_STAT_POTENCY] / 100) + 1);
|
||||
((Entity*)caster)->MStats.unlock();
|
||||
|
||||
//Ability Mod
|
||||
heal_amt += (int32)min((int32)info->get_ability_modifier(), (int32)(heal_amt / 2));
|
||||
|
|
|
@ -304,7 +304,7 @@ public:
|
|||
|
||||
void AddSpawnGroupChance(int32 group_id, float percent);
|
||||
|
||||
void RemoveSpawn(Spawn* spawn, bool delete_spawn = true, bool respawn = true, bool lock = true);
|
||||
void RemoveSpawn(Spawn* spawn, bool delete_spawn = true, bool respawn = true, bool lock = true, bool erase_from_spawn_list = true);
|
||||
void ProcessSpawnLocations();
|
||||
void SendQuestUpdates(Client* client, Spawn* spawn = 0);
|
||||
|
||||
|
@ -664,6 +664,8 @@ public:
|
|||
|
||||
void AddPendingSpawnRemove(int32 id);
|
||||
void ProcessSpawnRemovals();
|
||||
|
||||
bool SendRemoveSpawn(Client* client, Spawn* spawn, PacketStruct* packet = 0, bool delete_spawn = false);
|
||||
private:
|
||||
#ifndef WIN32
|
||||
pthread_t ZoneThread;
|
||||
|
@ -697,7 +699,6 @@ private:
|
|||
void SaveClients(); // never used outside zone server
|
||||
void CheckSendSpawnToClient(); // never used outside zone server
|
||||
void CheckSendSpawnToClient(Client* client, bool initial_login = false); // never used outside zone server
|
||||
bool SendRemoveSpawn(Client* client, Spawn* spawn, PacketStruct* packet = 0, bool delete_spawn = false); // never used outside zone server
|
||||
void CheckRemoveSpawnFromClient(Spawn* spawn); // never used outside zone server
|
||||
void SaveClient(Client* client); // never used outside zone server
|
||||
void ProcessFaction(Spawn* spawn, Client* client); // never used outside zone server
|
||||
|
|
Loading…
Add table
Reference in a new issue