Browse Source

Fix #507 - players dont gain hp while dead so revive works correctly at all times, Fix #232, added spell/item bonus type Power Cost Reduction type is 133, float eg 10.0 is 10% out of 100.0 for percentage

Emagi 1 year ago
parent
commit
3ba895b039

+ 1 - 1
EQ2/source/WorldServer/Combat.cpp

@@ -923,7 +923,7 @@ Skill* Entity::GetSkillByWeaponType(int8 type, int8 damage_type, bool update) {
 }
 
 bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_damage, int32 high_damage, const char* spell_name, int8 crit_mod, bool is_tick, bool no_calcs, bool ignore_attacker, LuaSpell* spell) {
-	if(!victim || victim->GetHP() == 0)
+	if(!victim || !victim->Alive() || victim->GetHP() == 0)
 		return false;
 
 	int8 hit_result = 0;

+ 4 - 4
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -2054,7 +2054,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 	}
 		case COMMAND_USEABILITY:{
 			if (sep && sep->arg[0][0] && sep->IsNumber(0)) {
-				if (client->GetPlayer()->GetHP() == 0) {
+				if (!client->GetPlayer()->Alive()) {
 					client->SimpleMessage(CHANNEL_COLOR_RED, "You cannot do that right now.");
 				}
 				else {
@@ -2469,7 +2469,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			int32 choice = 0;
 			if(sep && sep->arg[0] && sep->IsNumber(0))
 				choice = atoul(sep->arg[0]);
-			if(client->GetPlayer()->GetHP() == 0){ //dead and this is a revive request
+			if(!client->GetPlayer()->Alive()){ //dead and this is a revive request
 				client->HandlePlayerRevive(choice);
 			}
 			break;
@@ -4099,7 +4099,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			bool incombat = player->EngagedInCombat();
 			if(sep && sep->arg[0] && sep->IsNumber(0))
 				type = atoi(sep->arg[0]);
-			if(client->GetPlayer()->GetHP() == 0){
+			if(!client->GetPlayer()->Alive()){
 				client->SimpleMessage(CHANNEL_COLOR_RED,"You cannot do that right now.");
 				break;
 			}
@@ -6757,7 +6757,7 @@ void Commands::Command_Inventory(Client* client, Seperator* sep, EQ2_RemoteComma
 	{
 		LogWrite(COMMAND__INFO, 0, "Command", "command: %s", sep->argplus[0]);
 
-		if(client->GetPlayer()->GetHP() == 0)
+		if(!client->GetPlayer()->Alive())
 			client->SimpleMessage(CHANNEL_COLOR_RED,"You cannot do that right now.");
 		else if(sep->arg[1][0] && strncasecmp("destroy", sep->arg[0], 6) == 0 && sep->IsNumber(1))
 		{

+ 2 - 2
EQ2/source/WorldServer/Entity.cpp

@@ -908,7 +908,7 @@ void Entity::InCombat(bool val){
 }
 
 void Entity::DoRegenUpdate(){
-	if(GetHP() == 0)//dead
+	if(!Alive() || GetHP() == 0)//dead
 		return;
 	sint32 hp = GetHP();
 	sint32 power = GetPower();
@@ -1633,7 +1633,7 @@ void Entity::AddSpellBonus(LuaSpell* spell, int16 type, float value, int64 class
 	bonus->class_req = class_req;
 	bonus->race_req = race_req;
 	bonus->faction_req = faction_req;
-	bonus->tier = spell ? spell->spell->GetSpellTier() : 0;
+	bonus->tier = (spell && spell->spell) ? spell->spell->GetSpellTier() : 0;
 	bonus_list.Add(bonus);
 
 	if(IsNPC())

+ 1 - 0
EQ2/source/WorldServer/Items/Items.cpp

@@ -77,6 +77,7 @@ MasterItemList::MasterItemList(){
 	AddMappedItemStat(ITEM_STAT_TRANSMUTING, std::string("transmuting"));
 	AddMappedItemStat(ITEM_STAT_TRAPPING, std::string("trapping"));
 	AddMappedItemStat(ITEM_STAT_WEAPON_SKILLS, std::string("weapon skills"));
+	AddMappedItemStat(ITEM_STAT_POWER_COST_REDUCTION, std::string("power cost reduction"));
 }
 
 void MasterItemList::AddMappedItemStat(int32 id, std::string lower_case_name)

+ 1 - 0
EQ2/source/WorldServer/Items/Items.h

@@ -410,6 +410,7 @@ extern MasterItemList master_item_list;
 #define ITEM_STAT_TRANSMUTING  			130
 #define ITEM_STAT_TRAPPING  			131
 #define ITEM_STAT_WEAPON_SKILLS			132
+#define ITEM_STAT_POWER_COST_REDUCTION	133
 
 #define ITEM_STAT_VS_PHYSICAL			200
 #define ITEM_STAT_VS_HEAT				201 //elemental

+ 12 - 0
EQ2/source/WorldServer/Spawn.cpp

@@ -138,6 +138,7 @@ Spawn::Spawn(){
 	is_collector = false;
 	trigger_widget_id = 0;
 	scared_by_strong_players = false;
+	is_alive = true;
 }
 
 Spawn::~Spawn(){
@@ -1386,6 +1387,17 @@ void Spawn::SetHP(sint32 new_val, bool setUpdateFlags){
 	if(new_val == 0){
 		ClearRunningLocations();
 		CalculateRunningLocation(true);
+		
+		if(IsEntity()) {
+			is_alive = false;
+		}
+	}
+	if(IsNPC() && new_val > 0 && !is_alive) {
+		is_alive = true;
+	}
+	else if(IsPlayer() && new_val > 0 && !is_alive) {
+		LogWrite(SPAWN__ERROR, 0, "Spawn", "Cannot change player HP > 0 while dead (%s)!  Player must revive.", GetName());
+		return;
 	}
 	if(new_val > basic_info.max_hp)
 		SetInfo(&basic_info.max_hp, new_val, setUpdateFlags);

+ 4 - 1
EQ2/source/WorldServer/Spawn.h

@@ -717,7 +717,9 @@ public:
 	int16 GetQuestsRequiredOverride() {return req_quests_override;}
 	bool GetQuestsRequiredContinuedAccess() {return req_quests_continued_access;}
 
-	bool Alive(){ return GetHP() > 0; }
+	bool Alive(){ return is_alive; }
+	void SetAlive(bool val) { is_alive = val; }
+	
 	int16 GetLevel(){
 		return appearance.level;
 	}
@@ -1403,6 +1405,7 @@ private:
 	Mutex m_GridMutex;
 	bool is_collector;
 	bool scared_by_strong_players;
+	std::atomic<bool> is_alive;
 };
 
 #endif

+ 11 - 0
EQ2/source/WorldServer/Spells.cpp

@@ -1280,6 +1280,17 @@ int16 Spell::GetPowerRequired(Spawn* spawn){
 				}
 			}
 		}
+		
+		float power_reduction = ((Entity*)spawn)->GetStat(ITEM_STAT_POWER_COST_REDUCTION);
+		if(power_reduction > 0.0f) {
+				int16 power_to_reduce = (int16)(float)(power_req * (power_reduction/100.0f));
+				if(power_to_reduce > power_req) {
+					power_req = 0;
+				}
+				else {
+					power_req = power_req - power_to_reduce;
+				}
+		}
 	}
 	return power_req;
 }

+ 5 - 4
EQ2/source/WorldServer/client.cpp

@@ -593,6 +593,11 @@ void Client::HandlePlayerRevive(int32 point_id)
 	string zone_desc;
 	const char* location_name = "Unknown";
 
+	player->SetAlive(true);
+	player->SetResurrecting(true);
+	player->SetHP(player->GetTotalHP());
+	player->SetPower(player->GetTotalPower());
+	
 	//revive at zone safe coords
 	if (!revive_point)
 	{
@@ -616,14 +621,10 @@ void Client::HandlePlayerRevive(int32 point_id)
 		location_name = revive_point->location_name.c_str();
 		Zone(GetCurrentZone()->GetZoneName(), false);
 	}
-
-	player->SetResurrecting(true);
 	player->SetX(x);
 	player->SetY(y);
 	player->SetZ(z);
 	player->SetHeading(heading);
-	player->SetHP(player->GetTotalHP());
-	player->SetPower(player->GetTotalPower());
 
 	LogWrite(CCLIENT__DEBUG, 0, "Client", "Attempt Revive @ %s, %.2f, %.2f, %.2f, %.2f, HP: %i, Pow: %i, %s",
 		zone_desc.c_str(),

+ 1 - 1
EQ2/source/WorldServer/zoneserver.cpp

@@ -1994,7 +1994,7 @@ void ZoneServer::ProcessDrowning(){
 				drowning_victims.Get(client) = Timer::GetCurrentTime2() + 2000;
 				damage = player->GetTotalHP()/20 + player->GetInfoStruct()->get_hp_regen();
 				player->TakeDamage(damage);
-				if(player->GetHP() == 0)
+				if(!player->Alive())
 					dead_list.push_back(client);
 				player->SetCharSheetChanged(true);
 				SendCharSheetChanges(client);

+ 3 - 5
EQ2/source/common/MiscFunctions.cpp

@@ -689,19 +689,17 @@ bool IsNumber(const char *num) {
 }
 
 void PrintSep(Seperator *sep, const char *name) {
-#ifdef _DEBUG
 	int32 i = 0;
 
-	LogWrite(MISC__WARNING, 0, "Misc", "Printing sep %s", name ? name : "No Name");
+	LogWrite(MISC__DEBUG, 0, "Misc", "Printing sep %s", name ? name : "No Name");
 	if (!sep)
-		LogWrite(MISC__WARNING, 0, "Misc", "\tSep is null");
+		LogWrite(MISC__DEBUG, 0, "Misc", "\tSep is null");
 	else {
 		while (sep->arg[i] && strlen(sep->arg[i]) > 0) {
-			LogWrite(MISC__WARNING, 0, "Misc", "\t%i => %s", i, sep->arg[i]);
+			LogWrite(MISC__DEBUG, 0, "Misc", "\t%i => %s", i, sep->arg[i]);
 			i++;
 		}
 	}
-#endif
 }
 
 #define INI_IGNORE(c) (c == '\n' || c == '\r' || c == '#')