implemented air supply and lung capacity

This commit is contained in:
solar 2025-08-29 07:02:57 +01:00
parent a4e47d9180
commit 8ef369ee57
7 changed files with 68 additions and 5 deletions

View File

@ -700,7 +700,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
newbon->CHA += base_value;
break;
case SE_WaterBreathing:
// handled by client
newbon->WaterBreathing = base_value;
break;
case SE_CurrentMana:
newbon->ManaRegen += base_value;
@ -742,6 +742,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
case SE_TwoHandBash:
break;
case SE_SetBreathLevel:
newbon->BreathLevel += base_value;
break;
case SE_RaiseStatCap:
switch (limit_value) {

View File

@ -189,7 +189,8 @@ Client::Client() : Mob(
tmSitting(0),
parcel_timer(RuleI(Parcel, ParcelDeliveryDelay)),
lazy_load_bank_check_timer(1000),
bandolier_throttle_timer(0)
bandolier_throttle_timer(0),
underwater_timer(1000)
{
eqs = nullptr;
for (auto client_filter = FilterNone; client_filter < _FilterCount; client_filter = eqFilterType(client_filter + 1)) {
@ -497,7 +498,8 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
tmSitting(0),
parcel_timer(RuleI(Parcel, ParcelDeliveryDelay)),
lazy_load_bank_check_timer(1000),
bandolier_throttle_timer(0)
bandolier_throttle_timer(0),
underwater_timer(1000)
{
for (auto client_filter = FilterNone; client_filter < _FilterCount; client_filter = eqFilterType(client_filter + 1)) {
SetFilter(client_filter, FilterShow);
@ -13282,3 +13284,21 @@ bool Client::UncompleteTask(int task_id)
return task_state->UncompleteTask(task_id);
}
bool Client::IsUnderWater()
{
if (!zone->watermap) {
return false;
}
if (zone->GetZoneID() == Zones::KEDGE) {
return true;
}
auto underwater = glm::vec3(GetX(), GetY(), GetZ() + GetZOffset());
if (zone->IsWaterZone(underwater.z) || zone->watermap->InLiquid(underwater)) {
return true;
}
return false;
}

View File

@ -2037,6 +2037,7 @@ private:
int64 CalcHPRegen(bool bCombat = false);
int64 CalcManaRegen(bool bCombat = false);
int64 CalcBaseManaRegen();
int32 CalculateLungCapacity();
void DoHPRegen();
void DoManaRegen();
void DoStaminaHungerUpdate();
@ -2215,6 +2216,7 @@ private:
Timer parcel_timer; //Used to limit the number of parcels to one every 30 seconds (default). Changable via rule.
Timer lazy_load_bank_check_timer;
Timer bandolier_throttle_timer;
Timer underwater_timer;
bool m_lazy_load_bank = false;
int m_lazy_load_sent_bank_slots = 0;
@ -2433,6 +2435,7 @@ public:
bool IsFilteredAFKPacket(const EQApplicationPacket *p);
void CheckAutoIdleAFK(PlayerPositionUpdateClient_Struct *p);
void SyncWorldPositionsToClient(bool ignore_idle = false);
bool IsUnderWater();
};
#endif

View File

@ -1774,3 +1774,30 @@ int Client::GetRawACNoShield(int &shield_ac) const
}
return ac;
}
int32 Client::CalculateLungCapacity()
{
// Iksar and Frogloks do not benefit from Innate Lung Capacity and do not have STA penalty
if (GetBaseRace() == IKSAR) return 127;
if (GetBaseRace() == FROGLOK) return 256;
// Innate Lung Capacity AA gives 10%/25%/50% more
int base_lung_capacity = aabonuses.BreathLevel > 0 ? aabonuses.BreathLevel : 100;
int lung_capacity = base_lung_capacity;
// having less than 130 STA applies a reduction to air supply, but having more than 130 does not provide a bonus
int STA_penalty = GetSTA() - 30;
if (STA_penalty < 100) {
lung_capacity = base_lung_capacity * STA_penalty / 100;
if (lung_capacity < 10) {
lung_capacity = 10;
}
if (lung_capacity > base_lung_capacity) {
lung_capacity = base_lung_capacity;
}
}
return lung_capacity;
}

View File

@ -1707,8 +1707,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
m_pp.abilitySlotRefresh = 0;
}
/* Reset to max so they dont drown on zone in if its underwater */
m_pp.air_remaining = 60;
/* Check for PVP Zone status*/
if (zone->IsPVPZone())
m_pp.pvp = 1;

View File

@ -223,6 +223,18 @@ bool Client::Process() {
if (IsStunned() && stunned_timer.Check())
Mob::UnStun();
if (underwater_timer.Check()) {
if ((IsUnderWater() || GetZoneID() == Zones::THEGREY) &&
!spellbonuses.WaterBreathing && !aabonuses.WaterBreathing && !itembonuses.WaterBreathing) {
if (m_pp.air_remaining > 0) {
--m_pp.air_remaining;
}
}
else {
m_pp.air_remaining = CalculateLungCapacity();
}
}
cheat_manager.ClientProcess();
if (bardsong_timer.Check() && bardsong != 0) {

View File

@ -575,6 +575,8 @@ struct StatBonuses {
int aura_slots;
int trap_slots;
bool hunger; // Song of Sustenance -- min caps to 3500
int32 BreathLevel;
bool WaterBreathing;
int64 heroic_max_hp;
int64 heroic_max_mana;
int64 heroic_max_end;