Fix food/drink to match live

This commit is contained in:
Michael Cook (mackal) 2017-09-19 02:01:06 -04:00
parent 9634bef7fc
commit 8c9b852586
9 changed files with 82 additions and 82 deletions

View File

@ -276,6 +276,11 @@ enum {
#define SAYLINK_ITEM_ID 0xFFFFF #define SAYLINK_ITEM_ID 0xFFFFF
// consumption timers for food/drink here instead of rules because the client
// uses these. Times in ms.
#define CONSUMPTION_TIMER 46000
#define CONSUMPTION_MNK_TIMER 92000
/* /*
Developer configuration Developer configuration

View File

@ -117,7 +117,7 @@ RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVEN
RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients.
RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients. RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients.
RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap
RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT(Character, FoodLossPerUpdate, 32) // How much food/water you lose per stamina update
RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well.
RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field
RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225. RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225.

View File

@ -120,6 +120,13 @@ void Client::CalcBonuses()
if (GetMaxXTargets() != 5 + aabonuses.extra_xtargets) if (GetMaxXTargets() != 5 + aabonuses.extra_xtargets)
SetMaxXTargets(5 + aabonuses.extra_xtargets); SetMaxXTargets(5 + aabonuses.extra_xtargets);
// hmm maybe a better way to do this
int metabolism = spellbonuses.Metabolism + itembonuses.Metabolism + aabonuses.Metabolism;
int timer = GetClass() == MONK ? CONSUMPTION_MNK_TIMER : CONSUMPTION_TIMER;
timer = timer * (100 + metabolism) / 100;
if (timer != consume_food_timer.GetTimerTime())
consume_food_timer.SetTimer(timer);
} }
int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
@ -2503,6 +2510,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
new_bonus->MagicWeapon = true; new_bonus->MagicWeapon = true;
break; break;
case SE_Hunger:
new_bonus->hunger = true;
break;
case SE_IncreaseBlockChance: case SE_IncreaseBlockChance:
if (AdditiveWornBonus) if (AdditiveWornBonus)
new_bonus->IncreaseBlockChance += effect_value; new_bonus->IncreaseBlockChance += effect_value;

View File

@ -123,8 +123,7 @@ Client::Client(EQStreamInterface* ieqs)
hpupdate_timer(2000), hpupdate_timer(2000),
camp_timer(29000), camp_timer(29000),
process_timer(100), process_timer(100),
stamina_timer(40000), consume_food_timer(CONSUMPTION_TIMER),
consume_food_timer(60000),
zoneinpacket_timer(1000), zoneinpacket_timer(1000),
linkdead_timer(RuleI(Zone,ClientLinkdeadMS)), linkdead_timer(RuleI(Zone,ClientLinkdeadMS)),
dead_timer(2000), dead_timer(2000),
@ -8591,64 +8590,52 @@ void Client::SetConsumption(int32 in_hunger, int32 in_thirst)
void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool auto_consume) void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool auto_consume)
{ {
if(!item) { return; } if (!item)
return;
/* int increase = item->CastTime_ * 100;
Spell Bonuses 2 digit form - 10, 20, 25 etc. (10%, 20%, 25%) if (!auto_consume) // force feeding is half as effective
AA Bonus Ranks, 110, 125, 150 etc. (10%, 25%, 50%) increase /= 2;
*/
float aa_bonus = ((float) aabonuses.Metabolism - 100) / 100; if (increase < 0) // wasn't food? oh well
float item_bonus = (float) itembonuses.Metabolism / 100; return;
float spell_bonus = (float) spellbonuses.Metabolism / 100;
float metabolism_mod = 1 + spell_bonus + item_bonus + aa_bonus;
Log(Logs::General, Logs::Food, "Client::Consume() Metabolism bonuses spell_bonus: (%.2f) item_bonus: (%.2f) aa_bonus: (%.2f) final: (%.2f)",
spell_bonus,
item_bonus,
aa_bonus,
metabolism_mod
);
if (type == EQEmu::item::ItemTypeFood) { if (type == EQEmu::item::ItemTypeFood) {
int hunger_change = item->CastTime_ * metabolism_mod; increase = mod_food_value(item, increase);
hunger_change = mod_food_value(item, hunger_change);
if(hunger_change < 0) if (increase < 0)
return; return;
m_pp.hunger_level += hunger_change; m_pp.hunger_level += increase;
Log(Logs::General, Logs::Food, "Consuming food, points added to hunger_level: %i - current_hunger: %i", hunger_change, m_pp.hunger_level); Log(Logs::General, Logs::Food, "Consuming food, points added to hunger_level: %i - current_hunger: %i",
increase, m_pp.hunger_level);
DeleteItemInInventory(slot, 1, false);
if(!auto_consume) //no message if the client consumed for us
entity_list.MessageClose_StringID(this, true, 50, 0, EATING_MESSAGE, GetName(), item->Name);
Log(Logs::General, Logs::Food, "Eating from slot: %i", (int)slot);
}
else {
int thirst_change = item->CastTime_ * metabolism_mod;
thirst_change = mod_drink_value(item, thirst_change);
if(thirst_change < 0)
return;
m_pp.thirst_level += thirst_change;
DeleteItemInInventory(slot, 1, false); DeleteItemInInventory(slot, 1, false);
Log(Logs::General, Logs::Food, "Consuming drink, points added to thirst_level: %i current_thirst: %i", thirst_change, m_pp.thirst_level); if (!auto_consume) // no message if the client consumed for us
entity_list.MessageClose_StringID(this, true, 50, 0, EATING_MESSAGE, GetName(), item->Name);
if(!auto_consume) //no message if the client consumed for us Log(Logs::General, Logs::Food, "Eating from slot: %i", (int)slot);
} else {
increase = mod_drink_value(item, increase);
if (increase < 0)
return;
m_pp.thirst_level += increase;
DeleteItemInInventory(slot, 1, false);
Log(Logs::General, Logs::Food, "Consuming drink, points added to thirst_level: %i current_thirst: %i",
increase, m_pp.thirst_level);
if (!auto_consume) // no message if the client consumed for us
entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), item->Name); entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), item->Name);
Log(Logs::General, Logs::Food, "Drinking from slot: %i", (int)slot); Log(Logs::General, Logs::Food, "Drinking from slot: %i", (int)slot);
}
}
} }
void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg)

View File

@ -1458,7 +1458,6 @@ private:
Timer hpupdate_timer; Timer hpupdate_timer;
Timer camp_timer; Timer camp_timer;
Timer process_timer; Timer process_timer;
Timer stamina_timer;
Timer consume_food_timer; Timer consume_food_timer;
Timer zoneinpacket_timer; Timer zoneinpacket_timer;
Timer linkdead_timer; Timer linkdead_timer;

View File

@ -1410,6 +1410,10 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
drakkin_tattoo = m_pp.drakkin_tattoo; drakkin_tattoo = m_pp.drakkin_tattoo;
drakkin_details = m_pp.drakkin_details; drakkin_details = m_pp.drakkin_details;
// we know our class now, so we might have to fix our consume timer!
if (class_ == MONK)
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
/* If GM not set in DB, and does not meet min status to be GM, reset */ /* If GM not set in DB, and does not meet min status to be GM, reset */
if (m_pp.gm && admin < minStatusToBeGM) if (m_pp.gm && admin < minStatusToBeGM)
m_pp.gm = 0; m_pp.gm = 0;

View File

@ -524,10 +524,9 @@ bool Client::Process() {
DoEnduranceUpkeep(); DoEnduranceUpkeep();
} }
if (consume_food_timer.Check()) { // this is independent of the tick timer
m_pp.hunger_level = m_pp.hunger_level - 1; if (consume_food_timer.Check())
m_pp.thirst_level = m_pp.thirst_level - 1; DoStaminaHungerUpdate();
}
if (tic_timer.Check() && !dead) { if (tic_timer.Check() && !dead) {
CalcMaxHP(); CalcMaxHP();
@ -539,7 +538,6 @@ bool Client::Process() {
DoManaRegen(); DoManaRegen();
DoEnduranceRegen(); DoEnduranceRegen();
BuffProcess(); BuffProcess();
DoStaminaHungerUpdate();
if (tribute_timer.Check()) { if (tribute_timer.Check()) {
ToggleTribute(true); //re-activate the tribute. ToggleTribute(true); //re-activate the tribute.
@ -1834,32 +1832,37 @@ void Client::DoManaRegen() {
CheckManaEndUpdate(); CheckManaEndUpdate();
} }
void Client::DoStaminaHungerUpdate() { void Client::DoStaminaHungerUpdate()
if(!stamina_timer.Check()) {
return;
auto outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); auto outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct));
Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; Stamina_Struct *sta = (Stamina_Struct *)outapp->pBuffer;
Log(Logs::General, Logs::Food, "Client::DoStaminaHungerUpdate() hunger_level: %i thirst_level: %i before loss", m_pp.hunger_level, m_pp.thirst_level); Log(Logs::General, Logs::Food, "Client::DoStaminaHungerUpdate() hunger_level: %i thirst_level: %i before loss",
m_pp.hunger_level, m_pp.thirst_level);
if (zone->GetZoneID() != 151) { if (zone->GetZoneID() != 151 && !GetGM()) {
sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; int loss = RuleI(Character, FoodLossPerUpdate);
sta->water = m_pp.thirst_level > 6000 ? 6000 : m_pp.thirst_level; if (GetHorseId() != 0)
} loss *= 3;
else {
m_pp.hunger_level = EQEmu::Clamp(m_pp.hunger_level - loss, 0, 6000);
m_pp.thirst_level = EQEmu::Clamp(m_pp.thirst_level - loss, 0, 6000);
if (spellbonuses.hunger) {
m_pp.hunger_level = EQEmu::ClampLower(m_pp.hunger_level, 3500);
m_pp.thirst_level = EQEmu::ClampLower(m_pp.thirst_level, 3500);
}
sta->food = m_pp.hunger_level;
sta->water = m_pp.thirst_level;
} else {
// No auto food/drink consumption in the Bazaar // No auto food/drink consumption in the Bazaar
sta->food = 6000; sta->food = 6000;
sta->water = 6000; sta->water = 6000;
} }
Log(Logs::General, Logs::Food, Log(Logs::General, Logs::Food,
"Client::DoStaminaHungerUpdate() Current hunger_level: %i = (%i minutes left) thirst_level: %i = (%i minutes left) - after loss", "Client::DoStaminaHungerUpdate() Current hunger_level: %i = (%i minutes left) thirst_level: %i = (%i "
m_pp.hunger_level, "minutes left) - after loss",
m_pp.hunger_level, m_pp.hunger_level, m_pp.hunger_level, m_pp.thirst_level, m_pp.thirst_level);
m_pp.thirst_level,
m_pp.thirst_level
);
FastQueuePacket(&outapp); FastQueuePacket(&outapp);
} }

View File

@ -550,6 +550,7 @@ struct StatBonuses {
int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD
int aura_slots; int aura_slots;
int trap_slots; int trap_slots;
bool hunger; // Song of Sustenance -- min caps to 3500
}; };
typedef struct typedef struct

View File

@ -3656,16 +3656,6 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
break; break;
} }
case SE_Hunger: {
// this procedure gets called 7 times for every once that the stamina update occurs so we add
// 1/7 of the subtraction.
// It's far from perfect, but works without any unnecessary buff checks to bog down the server.
if (IsClient()) {
CastToClient()->m_pp.hunger_level += 5;
CastToClient()->m_pp.thirst_level += 5;
}
break;
}
case SE_Invisibility: case SE_Invisibility:
case SE_InvisVsAnimals: case SE_InvisVsAnimals:
case SE_InvisVsUndead: { case SE_InvisVsUndead: {