From 70fb1e37a562e7f07cbf8a3edfdecc585f12a935 Mon Sep 17 00:00:00 2001 From: Will Buck Date: Sat, 3 May 2025 22:24:52 -0500 Subject: [PATCH] Implement ENHANCES_MONSTER_CORRELATION --- modules/custom/cpp/ah_pagination.cpp | 4 +- scripts/actions/weaponskills/atonement.lua | 79 +- scripts/commands/time.lua | 126 ++- scripts/enum/item.lua | 102 ++ scripts/enum/mod.lua | 7 +- scripts/enum/vana_time.lua | 12 +- scripts/globals/combat/physical_utilities.lua | 29 +- scripts/globals/common.lua | 9 +- scripts/globals/mobs.lua | 8 +- scripts/globals/spells/absorb_spell.lua | 2 + scripts/globals/spells/enfeebling_spell.lua | 2 + scripts/globals/weaponskills.lua | 115 +-- scripts/globals/znm.lua | 38 +- scripts/globals/znm_data.lua | 68 +- .../missions/windurst/2_2_A_Testing_Time.lua | 78 +- .../quests/otherAreas/RQ2_Way_of_the_Cook.lua | 24 +- scripts/quests/windurst/SOB4_Onion_Rings.lua | 22 +- scripts/specs/core/CBaseEntity.lua | 4 +- scripts/specs/core/CItem.lua | 4 +- scripts/zones/Caedarva_Mire/npcs/qm8.lua | 4 +- .../Castle_Zvahl_Baileys/npcs/Switchstix.lua | 900 +++++++++++++++--- scripts/zones/Crawlers_Nest/npcs/qm9.lua | 4 +- scripts/zones/Lower_Jeuno/npcs/Chululu.lua | 6 +- .../zones/Lower_Jeuno/npcs/Kurou-Morou.lua | 4 +- scripts/zones/Mhaura/npcs/Nereus.lua | 8 +- scripts/zones/Nashmau/npcs/Dnegan.lua | 4 +- scripts/zones/Rabao/npcs/Leodarion.lua | 4 +- .../Windurst_Waters_[S]/npcs/Kocco_Ehllek.lua | 4 +- .../Yuhtunga_Jungle/npcs/Blue_Rafflesia.lua | 13 +- sql/item_mods.sql | 26 +- sql/item_mods_pet.sql | 14 +- sql/spell_list.sql | 4 +- src/common/CMakeLists.txt | 3 +- src/common/WheatyExceptionReport.cpp | 20 +- src/common/application.cpp | 5 +- src/common/cbasetypes.h | 8 - src/common/database.cpp | 9 +- src/common/database.h | 2 +- src/common/earth_time.h | 303 ++++++ src/common/ipp.h | 1 - src/common/logging.cpp | 2 +- src/common/mmo.h | 14 +- src/common/sql.cpp | 34 +- src/common/sql.h | 5 +- src/common/task_manager.cpp | 10 +- src/common/task_manager.h | 21 +- src/common/timer.cpp | 174 ---- src/common/timer.h | 59 +- src/common/utils.h | 6 +- src/common/vana_time.cpp | 356 ------- src/common/vana_time.h | 307 ++++-- src/common/watchdog.cpp | 8 +- src/common/watchdog.h | 9 +- src/common/xi.h | 36 + src/login/auth_session.cpp | 10 +- src/login/connect_server.cpp | 8 +- src/login/data_session.cpp | 14 +- src/login/session.h | 4 +- src/map/ability.cpp | 20 +- src/map/ability.h | 98 +- src/map/ai/ai_container.cpp | 26 +- src/map/ai/ai_container.h | 18 +- .../ai/controllers/automaton_controller.cpp | 26 +- src/map/ai/controllers/automaton_controller.h | 38 +- src/map/ai/controllers/controller.cpp | 2 +- src/map/ai/controllers/controller.h | 13 +- src/map/ai/controllers/mob_controller.cpp | 10 +- src/map/ai/controllers/mob_controller.h | 34 +- src/map/ai/controllers/pet_controller.cpp | 10 +- src/map/ai/controllers/pet_controller.h | 4 +- .../controllers/player_charm_controller.cpp | 6 +- .../ai/controllers/player_charm_controller.h | 6 +- src/map/ai/controllers/player_controller.cpp | 22 +- src/map/ai/controllers/player_controller.h | 16 +- src/map/ai/controllers/trust_controller.cpp | 12 +- src/map/ai/controllers/trust_controller.h | 18 +- src/map/ai/helpers/action_queue.cpp | 2 +- src/map/ai/helpers/action_queue.h | 15 +- src/map/ai/helpers/gambits_container.cpp | 10 +- src/map/ai/helpers/gambits_container.h | 6 +- src/map/ai/helpers/pathfind.cpp | 18 +- src/map/ai/helpers/pathfind.h | 5 +- src/map/ai/states/ability_state.cpp | 2 +- src/map/ai/states/ability_state.h | 6 +- src/map/ai/states/attack_state.cpp | 6 +- src/map/ai/states/attack_state.h | 6 +- src/map/ai/states/death_state.cpp | 8 +- src/map/ai/states/death_state.h | 10 +- src/map/ai/states/despawn_state.cpp | 4 +- src/map/ai/states/despawn_state.h | 4 +- src/map/ai/states/inactive_state.cpp | 6 +- src/map/ai/states/inactive_state.h | 12 +- src/map/ai/states/item_state.cpp | 8 +- src/map/ai/states/item_state.h | 22 +- src/map/ai/states/magic_state.cpp | 26 +- src/map/ai/states/magic_state.h | 14 +- src/map/ai/states/mobskill_state.cpp | 9 +- src/map/ai/states/mobskill_state.h | 8 +- src/map/ai/states/petskill_state.cpp | 9 +- src/map/ai/states/petskill_state.h | 8 +- src/map/ai/states/raise_state.cpp | 2 +- src/map/ai/states/raise_state.h | 4 +- src/map/ai/states/range_state.cpp | 6 +- src/map/ai/states/range_state.h | 16 +- src/map/ai/states/respawn_state.cpp | 10 +- src/map/ai/states/respawn_state.h | 8 +- src/map/ai/states/state.cpp | 6 +- src/map/ai/states/state.h | 19 +- src/map/ai/states/synth_state.cpp | 4 +- src/map/ai/states/synth_state.h | 6 +- src/map/ai/states/trigger_state.cpp | 2 +- src/map/ai/states/trigger_state.h | 4 +- src/map/ai/states/weaponskill_state.cpp | 4 +- src/map/ai/states/weaponskill_state.h | 6 +- src/map/attack.cpp | 11 +- src/map/battlefield.cpp | 42 +- src/map/battlefield.h | 59 +- src/map/battlefield_handler.cpp | 6 +- src/map/battlefield_handler.h | 23 +- src/map/char_recast_container.cpp | 10 +- src/map/char_recast_container.h | 2 +- src/map/conquest_system.cpp | 12 +- src/map/conquest_system.h | 2 +- src/map/enmity_container.cpp | 1 + src/map/entities/baseentity.cpp | 2 +- src/map/entities/baseentity.h | 5 +- src/map/entities/battleentity.cpp | 49 +- src/map/entities/battleentity.h | 36 +- src/map/entities/charentity.cpp | 104 +- src/map/entities/charentity.h | 110 +-- src/map/entities/mobentity.cpp | 26 +- src/map/entities/mobentity.h | 22 +- src/map/entities/npcentity.cpp | 2 +- src/map/entities/npcentity.h | 2 +- src/map/entities/petentity.cpp | 29 +- src/map/entities/petentity.h | 16 +- src/map/entities/trustentity.cpp | 2 +- src/map/fishingcontest.cpp | 6 +- src/map/guild.cpp | 5 +- src/map/guild.h | 2 +- src/map/instance.cpp | 20 +- src/map/instance.h | 32 +- src/map/instance_loader.cpp | 2 +- src/map/item_container.cpp | 2 +- src/map/item_container.h | 5 +- src/map/items.h | 1 + src/map/items/item.cpp | 21 +- src/map/items/item.h | 4 +- src/map/items/item_usable.cpp | 58 +- src/map/items/item_usable.h | 55 +- src/map/latent_effect_container.cpp | 30 +- src/map/linkshell.cpp | 2 +- src/map/lua/lua_ability.cpp | 4 +- src/map/lua/lua_action.cpp | 4 +- src/map/lua/lua_baseentity.cpp | 112 ++- src/map/lua/lua_baseentity.h | 8 +- src/map/lua/lua_battlefield.cpp | 18 +- src/map/lua/lua_instance.cpp | 7 +- src/map/lua/lua_item.cpp | 14 +- src/map/lua/lua_item.h | 2 +- src/map/lua/lua_spell.cpp | 4 +- src/map/lua/lua_statuseffect.cpp | 24 +- src/map/lua/lua_treasure_pool.cpp | 2 +- src/map/lua/lua_zone.cpp | 5 +- src/map/lua/luautils.cpp | 96 +- src/map/lua/luautils.h | 1 - src/map/map_constants.h | 5 +- src/map/map_networking.cpp | 15 +- src/map/map_networking.h | 2 +- src/map/map_server.cpp | 61 +- src/map/map_server.h | 5 +- src/map/map_session.h | 21 +- src/map/map_session_container.cpp | 8 +- src/map/map_socket.cpp | 2 +- src/map/map_socket.h | 2 +- src/map/mobskill.cpp | 12 +- src/map/mobskill.h | 86 +- src/map/modifier.h | 41 +- src/map/monstrosity.cpp | 6 +- src/map/navmesh.cpp | 2 +- src/map/packet_guard.cpp | 35 +- src/map/packet_system.cpp | 47 +- src/map/packets/action.cpp | 6 +- src/map/packets/action.h | 4 +- src/map/packets/bazaar_item.cpp | 8 +- src/map/packets/char_check.cpp | 8 +- src/map/packets/char_recast.cpp | 8 +- src/map/packets/char_status.cpp | 7 +- src/map/packets/conquest_map.cpp | 2 +- src/map/packets/fish_ranking.cpp | 2 +- src/map/packets/inventory_item.cpp | 9 +- src/map/packets/objective_utility.cpp | 2 +- src/map/packets/roe_sparkupdate.cpp | 6 +- src/map/packets/server_message.cpp | 2 +- src/map/packets/status_effects.cpp | 18 +- src/map/packets/treasure_find_item.cpp | 2 +- src/map/packets/zone_in.cpp | 14 +- src/map/party.cpp | 48 +- src/map/party.h | 4 +- src/map/pch.h | 1 - src/map/petskill.cpp | 12 +- src/map/petskill.h | 80 +- src/map/recast_container.cpp | 47 +- src/map/recast_container.h | 17 +- src/map/roe.cpp | 42 +- src/map/spell.cpp | 22 +- src/map/spell.h | 78 +- src/map/status_effect.cpp | 20 +- src/map/status_effect.h | 26 +- src/map/status_effect_container.cpp | 120 ++- src/map/status_effect_container.h | 6 +- src/map/time_server.cpp | 189 ++-- src/map/time_server.h | 3 +- src/map/timetriggers.cpp | 15 +- src/map/timetriggers.h | 5 +- src/map/transport.cpp | 67 +- src/map/transport.h | 21 +- src/map/treasure_pool.cpp | 32 +- src/map/treasure_pool.h | 14 +- src/map/utils/auctionutils.cpp | 8 +- src/map/utils/battleutils.cpp | 169 ++-- src/map/utils/battleutils.h | 16 +- src/map/utils/charutils.cpp | 241 ++--- src/map/utils/charutils.h | 14 +- src/map/utils/dboxutils.cpp | 2 +- src/map/utils/fishingutils.cpp | 47 +- src/map/utils/fishingutils.h | 1 - src/map/utils/gardenutils.cpp | 12 +- src/map/utils/guildutils.cpp | 6 +- src/map/utils/itemutils.cpp | 8 +- src/map/utils/mobutils.cpp | 4 +- src/map/utils/petutils.cpp | 10 +- src/map/utils/petutils.h | 10 +- src/map/utils/serverutils.cpp | 11 +- src/map/utils/serverutils.h | 2 +- src/map/utils/synthutils.cpp | 3 +- src/map/utils/zoneutils.cpp | 8 +- src/map/utils/zoneutils.h | 2 +- src/map/weapon_skill.cpp | 4 +- src/map/weapon_skill.h | 44 +- src/map/zone.cpp | 49 +- src/map/zone.h | 9 +- src/map/zone_entities.cpp | 28 +- src/map/zone_entities.h | 18 +- src/map/zone_instance.cpp | 8 +- src/map/zone_instance.h | 5 +- src/search/search_handler.cpp | 5 +- src/world/daily_tally.cpp | 4 + src/world/http_server.cpp | 2 +- src/world/http_server.h | 5 +- src/world/time_server.cpp | 123 ++- src/world/time_server.h | 2 +- src/world/world_server.cpp | 17 +- tools/ci/check_lua_binding_usage.py | 7 +- tools/run_clang_format.sh | 4 +- 255 files changed, 4006 insertions(+), 3194 deletions(-) create mode 100644 src/common/earth_time.h delete mode 100644 src/common/timer.cpp delete mode 100644 src/common/vana_time.cpp diff --git a/modules/custom/cpp/ah_pagination.cpp b/modules/custom/cpp/ah_pagination.cpp index 36683964ab4..0c1f19954d5 100644 --- a/modules/custom/cpp/ah_pagination.cpp +++ b/modules/custom/cpp/ah_pagination.cpp @@ -59,8 +59,8 @@ class AHPaginationModule : public CPPModule const auto action = data.ref(0x04); if (action == 0x05) { - const uint32 curTick = gettick(); - if (curTick - PChar->m_AHHistoryTimestamp > 1500) + const timer::time_point curTick = timer::now(); + if (curTick - PChar->m_AHHistoryTimestamp > 1500ms) { // Not const, because we're going to increment it below // This will get wiped on zoning diff --git a/scripts/actions/weaponskills/atonement.lua b/scripts/actions/weaponskills/atonement.lua index 1d3ed33716c..be9686f848d 100644 --- a/scripts/actions/weaponskills/atonement.lua +++ b/scripts/actions/weaponskills/atonement.lua @@ -24,9 +24,10 @@ local weaponskillObject = {} weaponskillObject.onUseWeaponSkill = function(player, target, wsID, tp, primary, action, taChar) local params = {} - params.numHits = 2 - params.ftpMod = { 1, 1.25, 1.5 } - params.str_wsc = 0.4 params.vit_wsc = 0.5 + params.numHits = 2 + params.ftpMod = { 1, 1.25, 1.5 } + params.str_wsc = 0.4 + params.vit_wsc = 0.5 params.enmityMult = 1 -- Apply aftermath @@ -41,60 +42,56 @@ weaponskillObject.onUseWeaponSkill = function(player, target, wsID, tp, primary, } local calcParams = { - wsID = wsID, - criticalHit = false, - tpHitsLanded = 0, + wsID = wsID, + criticalHit = false, + tpHitsLanded = 0, extraHitsLanded = 0, shadowsAbsorbed = 0, - bonusTP = 0 + bonusTP = 0 } local damage = 0 - if target:getObjType() ~= xi.objType.MOB then -- this isn't correct but might as well use what was originally here if someone uses this on a non-mob - if xi.settings.main.USE_ADOULIN_WEAPON_SKILL_CHANGES then - params.ftpMod = { 1, 1.5, 2 } - end + -- Calculate damage caps (item level and level based) + local levelUsed = player:getAverageItemLevel() > 0 and player:getAverageItemLevel() or player:getMainLvl() + -- local hitDamageCap = (levelUsed + 14) * 5 -- iLvl 119 -> 665 + local globalDamageCap = levelUsed * 10 -- iLvl 119 -> 1190 + + -- If the target isn't a mob,theres no enmity to calculate with. + if target:getObjType() ~= xi.objType.MOB then + params.ftpMod = { 1, 1.5, 2 } damage, calcParams.criticalHit, calcParams.tpHitsLanded, calcParams.extraHitsLanded = xi.weaponskills.doPhysicalWeaponskill(player, target, wsID, params, tp, action, primary, taChar) - else - local dmg - if xi.settings.main.USE_ADOULIN_WEAPON_SKILL_CHANGES then - dmg = (target:getCE(player) + target:getVE(player)) / 6 - -- tp affects enmity multiplier, 1.0 at 1k, 1.5 at 2k, 2.0 at 3k. Gorget/Belt adds 100 tp each. - params.enmityMult = params.enmityMult + (tp + xi.weaponskills.handleWSGorgetBelt(player) * 1000 - 1000) / 2000 - params.enmityMult = utils.clamp(params.enmityMult, 1, 2) -- necessary because of Gorget/Belt bonus - else - local effectiveTP = tp + xi.weaponskills.handleWSGorgetBelt(player) * 1000 - effectiveTP = utils.clamp(effectiveTP, 0, 3000) -- necessary because of Gorget/Belt bonus - local ceMod = xi.weaponskills.fTP(effectiveTP, { 0.09, 0.11, 0.20 }) -- CE portion of Atonement - local veMod = xi.weaponskills.fTP(effectiveTP, { 0.11, 0.14, 0.25 }) -- VE portion of Atonement - dmg = math.floor(target:getCE(player) * ceMod) + math.floor(target:getVE(player) * veMod) - end + return calcParams.tpHitsLanded, calcParams.extraHitsLanded, calcParams.criticalHit, damage + end - dmg = utils.clamp(dmg, 0, player:getMainLvl() * 10) -- Damage is capped to player's level * 10, before WS damage mods - damage = target:breathDmgTaken(dmg) - if player:getMod(xi.mod.WEAPONSKILL_DAMAGE_BASE + wsID) > 0 then - damage = damage * (100 + player:getMod(xi.mod.WEAPONSKILL_DAMAGE_BASE + wsID)) / 100 - end + -- Regular + local dmg = (target:getCE(player) + target:getVE(player)) / 6 + -- tp affects enmity multiplier, 1.0 at 1k, 1.5 at 2k, 2.0 at 3k. Gorget/Belt adds 100 tp each. + params.enmityMult = params.enmityMult + (tp + xi.combat.physical.calculateFTPBonus(player) * 1000 - 1000) / 2000 + params.enmityMult = utils.clamp(params.enmityMult, 1, 2) -- necessary because of Gorget/Belt bonus - damage = damage * xi.settings.main.WEAPON_SKILL_POWER - calcParams.finalDmg = damage + damage = target:breathDmgTaken(dmg) + if player:getMod(xi.mod.WEAPONSKILL_DAMAGE_BASE + wsID) > 0 then + damage = damage * (100 + player:getMod(xi.mod.WEAPONSKILL_DAMAGE_BASE + wsID)) / 100 + end - if damage > 0 then - if player:getOffhandDmg() > 0 then - calcParams.tpHitsLanded = 2 - else - calcParams.tpHitsLanded = 1 - end + damage = utils.clamp(damage, 0, globalDamageCap) + calcParams.finalDmg = damage - -- Atonement always yields the a TP return of a 2 hit WS (unless it does 0 damage), because if one hit lands, both hits do. - calcParams.extraHitsLanded = 1 + if damage > 0 then + if player:getOffhandDmg() > 0 then + calcParams.tpHitsLanded = 2 + else + calcParams.tpHitsLanded = 1 end - damage = xi.weaponskills.takeWeaponskillDamage(target, player, params, primary, attack, calcParams, action) + -- Atonement always yields the a TP return of a 2 hit WS (unless it does 0 damage), because if one hit lands, both hits do. + calcParams.extraHitsLanded = 1 end + damage = xi.weaponskills.takeWeaponskillDamage(target, player, params, primary, attack, calcParams, action) + return calcParams.tpHitsLanded, calcParams.extraHitsLanded, calcParams.criticalHit, damage end diff --git a/scripts/commands/time.lua b/scripts/commands/time.lua index 58480e750bb..194748d7708 100644 --- a/scripts/commands/time.lua +++ b/scripts/commands/time.lua @@ -1,37 +1,121 @@ ----------------------------------- -- func: time --- desc: Sets the custom time offset of the CVanaTime instance. +-- desc: Prints time info. ----------------------------------- ---@type TCommand local commandObj = {} commandObj.cmdprops = { - permission = 4, - parameters = 'i' + permission = 1, + parameters = '' } -local function error(player) - player:printToPlayer('!time ') - player:printToPlayer(string.format('Vana\'diel: %d/%d/%d/%d/%02d', VanadielYear(), VanadielMonth(), VanadielDayOfTheMonth(), VanadielHour(), VanadielMinute())) -end +commandObj.onTrigger = function(player) + local channel = xi.msg.channel.SYSTEM_3 + local elementalDayName = + { + 'Firesday', + 'Earthsday', + 'Watersday', + 'Windsday', + 'Iceday', + 'Lightningday', + 'Lightsday', + 'Darksday', + } + local totdName = + { + 'Midnight', + 'New Day', + 'Dawn', + 'Daytime', + 'Dusk', + 'Evening', + 'Night', + } + local raceName = + { + 'Hume Male', + 'Hume Female', + 'Elvaan Male', + 'Elvaan Female', + 'Taru Male', + 'Taru Female', + 'Mithra', + 'Galka', + } + local rseZoneName = + { + 'Ordelle\'s Caves', + 'Gusgen Mines', + 'Maze of Shakhrami', + } + local earthDayName = + { + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + } + -- Time and Date + local year = VanadielYear() + 886 + local month = VanadielMonth() + local day = VanadielDayOfTheMonth() + local dayElement = elementalDayName[VanadielDayOfTheWeek() + 1] + local hour = VanadielHour() + local minute = VanadielMinute() + local totd = totdName[VanadielTOTD()] or 'None' + player:printToPlayer(fmt('It has been {} Vana\'diel days ({} seconds) since the Vana\'diel epoch.', VanadielUniqueDay(), VanadielTime()), channel) + player:printToPlayer(fmt('The next Vana\'diel day is in {} seconds.', getVanaMidnight() - os.time()), channel) + player:printToPlayer(fmt('Vana\'diel: {}/{}/{}, {}, {}:{:02} ({}, {} days into the year)', year, month, day, dayElement, hour, minute, totd, VanadielDayOfTheYear()), channel) -commandObj.onTrigger = function(player, offset) - -- validate offset - if offset == nil then - error(player) - return + -- Moon + local moonDirection = VanadielMoonDirection() + local moonPhase = VanadielMoonPhase() + local moonType = IsMoonFull() and 'Full Moon' or IsMoonNew() and 'New Moon' + if not moonType then + if moonDirection == 1 then + if moonPhase <= 93 and moonPhase >= 62 then + moonType = 'Waning Gibbous' + elseif moonPhase <= 60 and moonPhase >= 43 then + moonType = 'Last Quarter' + elseif moonPhase <= 40 and moonPhase >= 12 then + moonType = 'Waning Crescent' + end + elseif moonDirection == 2 then + if moonPhase >= 7 and moonPhase <= 38 then + moonType = 'Waxing Crescent' + elseif moonPhase >= 40 and moonPhase <= 55 then + moonType = 'First Quarter' + elseif moonPhase >= 57 and moonPhase <= 88 then + moonType = 'Waxing Gibbous' + end + end end - -- time offset - local result = SetVanadielTimeOffset(offset) - if result == nil then - error(player) - return - else - player:printToPlayer('Time changed!') - player:printToPlayer(string.format('Vana\'diel: %d/%d/%d/%d/%02d', VanadielYear(), VanadielMonth(), VanadielDayOfTheMonth(), VanadielHour(), VanadielMinute())) - end + player:printToPlayer(fmt(' {} ({}%)', moonType, moonPhase), channel) + + -- Earth time + local utcTimestamp = GetSystemTime() + local secondsToMidnight = JstMidnight() - utcTimestamp + local hoursToMidnight = math.floor(secondsToMidnight / (60 * 60)) + secondsToMidnight = secondsToMidnight - (hoursToMidnight * 60 * 60) + local minutesToMidnight = math.floor(secondsToMidnight / 60) + secondsToMidnight = secondsToMidnight - (minutesToMidnight * 60) + local jstHours = 23 - hoursToMidnight + local jstMinutes = 59 - minutesToMidnight + local jstSeconds = 59 - secondsToMidnight + local weeklyResetDays = math.floor((NextJstWeek() - utcTimestamp) / (24 * 60 * 60)) + player:printToPlayer(fmt('Japan: {}, {}:{:02}:{:02} (weekly reset in {} days)', earthDayName[JstWeekday() + 1], jstHours, jstMinutes, jstSeconds, weeklyResetDays), channel) + + -- RSE + local rseRace = raceName[VanadielRSERace()] + local rseLocation = rseZoneName[VanadielRSELocation() + 1] + player:printToPlayer(fmt('Current RSE is {} in {}.', rseRace, rseLocation), channel) end return commandObj diff --git a/scripts/enum/item.lua b/scripts/enum/item.lua index e3b278b8e48..cca739c4e3a 100644 --- a/scripts/enum/item.lua +++ b/scripts/enum/item.lua @@ -256,7 +256,9 @@ xi.item = IRON_SHEET = 662, MYTHRIL_SHEET = 663, DARKSTEEL_SHEET = 664, + ADAMAN_SHEET = 665, STEEL_SHEET = 666, + ORICHALCUM_SHEET = 668, ALUMINUM_SHEET = 670, CHUNK_OF_ALUMINUM_ORE = 678, ADAMAN_CHAIN = 683, @@ -311,6 +313,7 @@ xi.item = CHUNK_OF_DURIUM_ORE = 756, SILVER_CHAIN = 760, GOLD_CHAIN = 761, + ORICHALCUM_CHAIN = 763, ORMOLU_INGOT = 766, FLINT_STONE = 768, RED_ROCK = 769, @@ -408,6 +411,7 @@ xi.item = HANDFUL_OF_DRAGON_SCALES = 867, HANDFUL_OF_PUGIL_SCALES = 868, LIZARD_MOLT = 869, + SQUARE_OF_AMALTHEIA_LEATHER = 875, KARAKUL_SKIN = 878, SQUARE_OF_KARAKUL_LEATHER = 879, BONE_CHIP = 880, @@ -669,7 +673,10 @@ xi.item = CHUNK_OF_DARK_ORE = 1262, TONBERRY_RATTLE = 1266, BAG_OF_BEE_LARVAE = 1267, + PIGEONS_BLOOD_RUBY = 1271, + TARASQUE_SKIN = 1276, SPOOL_OF_TWINTHREAD = 1278, + SPOOL_OF_ARACHNE_THREAD = 1294, TWINCOON = 1295, HAKUTAKU_EYE_CLUSTER = 1298, FIRE_BEAD = 1299, @@ -782,6 +789,7 @@ xi.item = SEAL_OF_BYAKKO = 1406, SEAL_OF_SUZAKU = 1407, BOTTLE_OF_ILLUMININK = 1408, + SPOOL_OF_SIRENS_MACRAME = 1409, SWEET_WILLIAM = 1410, PHALAENOPSIS = 1411, OLIVE_FLOWER = 1412, @@ -908,6 +916,21 @@ xi.item = CLOUDY_ORB = 1551, SKY_ORB = 1552, THEMIS_ORB = 1553, + ATTESTATION_OF_MIGHT = 1556, + ATTESTATION_OF_CELERITY = 1557, + ATTESTATION_OF_GLORY = 1558, + ATTESTATION_OF_RIGHTEOUSNESS = 1559, + ATTESTATION_OF_BRAVERY = 1560, + ATTESTATION_OF_FORCE = 1561, + ATTESTATION_OF_VIGOR = 1562, + ATTESTATION_OF_FORTITUDE = 1563, + ATTESTATION_OF_LEGERITY = 1564, + ATTESTATION_OF_DECISIVENESS = 1565, + ATTESTATION_OF_SACRIFICE = 1566, + ATTESTATION_OF_VIRTUE = 1567, + ATTESTATION_OF_TRANSCENDENCE = 1568, + ATTESTATION_OF_HARMONY = 1569, + ATTESTATION_OF_ACCURACY = 1570, MYSTIC_FRAGMENT = 1571, ORNATE_FRAGMENT = 1572, HOLY_FRAGMENT = 1573, @@ -1036,6 +1059,7 @@ xi.item = FREE_CHOCOPASS = 1789, EUVHI_ORGAN = 1818, LUMINION_CHIP = 1819, + ATTESTATION_OF_INVULNERABILITY = 1821, SUPERNAL_FRAGMENT = 1822, SHRIMP_LANTERN = 1823, HAUNTED_MULETA = 1824, @@ -4362,6 +4386,7 @@ xi.item = ELM_SHIELD = 12291, MAHOGANY_SHIELD = 12292, OAK_SHIELD = 12293, + ROUND_SHIELD = 12295, GENBUS_SHIELD = 12296, PARANA_SHIELD = 12298, ASPIS = 12299, @@ -4395,6 +4420,7 @@ xi.item = LIGHT_BUCKLER = 12375, ASTRAL_ASPIS = 12382, ACHERON_SHIELD = 12385, + KOENIG_SHIELD = 12387, MERCENARYS_TARGE = 12389, WRESTLERS_ASPIS = 12390, HEALERS_SHIELD = 12391, @@ -4710,6 +4736,7 @@ xi.item = PEACOCK_CHARM = 13056, BUBURIMU_GORGET = 13057, BLOODBEAD_AMULET = 13058, + FEATHER_COLLAR_P1 = 13060, IRON_MUSKETEERS_GORGET = 13064, GORGET_P1 = 13065, FEATHER_COLLAR = 13075, @@ -4820,6 +4847,7 @@ xi.item = BRONZE_MOOGLE_BELT = 13218, ROYAL_KNIGHTS_BELT = 13220, MERCENARY_CAPTAINS_BELT = 13221, + SWORDBELT_P1 = 13232, MASTER_BELT = 13236, SURVIVAL_BELT = 13237, DRUIDS_ROPE = 13238, @@ -5542,6 +5570,8 @@ xi.item = ARGUTE_BRACERS_P1 = 15041, GOTHIC_GAUNTLETS = 15042, RELIC_SHIELD = 15066, + BULWARK_SHIELD = 15067, + DYNAMIS_SHIELD = 15068, ANCILE = 15069, AEGIS_75 = 15070, WARRIORS_MASK = 15072, @@ -6267,6 +6297,7 @@ xi.item = BRONZE_KNUCKLES = 16390, BRASS_KNUCKLES = 16391, METAL_KNUCKLES = 16392, + KOENIGS_KNUCKLES = 16396, CAT_BAGHNAKHS = 16405, BRASS_BAGHNAKHS = 16407, LYNX_BAGHNAKHS = 16409, @@ -6279,6 +6310,7 @@ xi.item = BRONZE_DAGGER = 16448, BRASS_DAGGER = 16449, DAGGER = 16450, + MISERICORDE = 16452, BASELARD = 16455, COMBAT_CASTERS_DAGGER = 16463, BRONZE_KNIFE = 16465, @@ -6290,6 +6322,7 @@ xi.item = BEESTINGER = 16486, MINSTRELS_DAGGER = 16487, BRONZE_KNIFE_P1 = 16491, + POISON_DAGGER = 16496, SLEEP_DAGGER = 16497, ASPIR_KNIFE = 16509, BURNITE_SHELL_STONE = 16511, @@ -6308,6 +6341,7 @@ xi.item = BRONZE_SWORD = 16535, IRON_SWORD = 16536, MYTHRIL_SWORD = 16537, + WING_SWORD = 16542, ROYAL_ARCHERS_SWORD = 16544, BROADSWORD = 16545, HALLOWED_SWORD = 16550, @@ -6325,6 +6359,7 @@ xi.item = HUNTING_SWORD = 16576, CLAYMORE = 16583, MYTHRIL_CLAYMORE = 16584, + DARKSTEEL_CLAYMORE = 16585, ROYAL_GUARDS_SWORD = 16599, ROYAL_SWORDSMANS_BLADE = 16601, PERDU_SWORD = 16602, @@ -6342,6 +6377,8 @@ xi.item = RUSTY_PICK = 16655, ORCISH_AXE = 16656, TABAR = 16657, + DARKSTEEL_TABAR = 16658, + TABARZIN = 16659, DOOM_TABAR = 16660, LIGHT_AXE = 16667, COMBAT_CASTERS_AXE = 16669, @@ -6360,6 +6397,7 @@ xi.item = CENTURIONS_AXE = 16712, NECKCHOPPER = 16714, EXECUTIONER = 16723, + HEAVY_DARKSTEEL_AXE = 16724, FORSETIS_AXE = 16726, SCHWARZ_AXT = 16728, AXE_OF_TRIALS = 16735, @@ -6372,10 +6410,13 @@ xi.item = BRONZE_ZAGHNAL = 16768, BRASS_ZAGHNAL = 16769, ZAGHNAL = 16770, + SCYTHE = 16774, MERCENARY_CAPTAINS_SCYTHE = 16776, + DEATH_SCYTHE = 16777, LEGIONNAIRES_SCYTHE = 16780, VASSAGOS_SCYTHE = 16788, SCYTHE_OF_TRIALS = 16793, + BONE_SCYTHE = 16794, RAVEN_SCYTHE = 16798, SENIOR_GOLD_MUSKETEERS_SCYTHE = 16799, ROYAL_GUARDS_FLEURET = 16805, @@ -6388,7 +6429,9 @@ xi.item = BRONZE_SPEAR = 16833, BRASS_SPEAR = 16834, SPEAR = 16835, + HALBERD = 16836, TRIDENT = 16837, + WYVERN_SPEAR = 16841, ROYAL_SQUIRES_HALBERD = 16844, LANCE = 16845, MERCURIAL_SPEAR = 16850, @@ -6403,6 +6446,9 @@ xi.item = RESERVE_CAPTAINS_LANCE = 16893, KUNAI = 16896, KAGEBOSHI = 16897, + WAKIZASHI = 16900, + SAKURAFUBUKI = 16902, + KABUTOWARI = 16903, SHINOGI = 16913, MERCENARYS_GREATSWORD = 16930, GERWITZS_SWORD = 16940, @@ -6410,8 +6456,11 @@ xi.item = SWORD_OF_TRIALS = 16952, RESERVE_CAPTAINS_GREATSWORD = 16953, PLATOON_SWORD = 16959, + TACHI = 16966, + MIKAZUKI = 16967, KAMEWARI = 16968, YUKITSUGU = 16971, + KAZARIDACHI = 16972, DOTANUKI = 16974, ONIMARU = 16976, UCHIGATANA_P1 = 16978, @@ -6460,6 +6509,7 @@ xi.item = ONION_ROD = 17068, CHOCOBO_WAND = 17074, EARTH_WAND = 17076, + HOLY_MAUL = 17080, BRASS_ROD = 17081, TACTICIAN_MAGICIANS_WAND = 17082, TIME_HAMMER = 17083, @@ -6467,6 +6517,7 @@ xi.item = HOLLY_STAFF = 17089, ELM_STAFF = 17090, OAK_STAFF = 17091, + MAHOGANY_STAFF = 17092, WISE_WIZARDS_STAFF = 17094, ASH_POLE = 17095, HOLLY_POLE = 17096, @@ -6490,6 +6541,7 @@ xi.item = LONGBOW = 17160, POWER_BOW = 17161, GREAT_BOW = 17162, + WAR_BOW = 17164, ROYAL_ARCHERS_LONGBOW = 17167, SPEED_BOW = 17170, LONGBOW_P1 = 17177, @@ -6515,8 +6567,10 @@ xi.item = ZISKAS_CROSSBOW = 17246, RIKONODO = 17247, ARQUEBUS = 17248, + HELLFIRE = 17251, CULVERIN = 17252, MUSKETEER_GUN = 17253, + PIRATES_GUN = 17259, PLATOON_GUN = 17271, MILITARY_GUN = 17272, COFFINMAKER = 17275, @@ -6564,8 +6618,10 @@ xi.item = PICCOLO = 17347, FAERIE_PICCOLO = 17349, GEMSHORN = 17351, + HORN = 17352, MAPLE_HARP = 17353, LAMIA_HARP = 17356, + SHOFAR = 17362, FRENZY_FIFE = 17365, MARYS_HORN = 17366, ROYAL_SPEARMANS_HORN = 17367, @@ -6822,6 +6878,7 @@ xi.item = BAILATHORN = 18138, BOMB_CORE = 18139, UNGUR_BOOMERANG = 18141, + SHIGETO_BOW = 18142, BOW_OF_TRIALS = 18144, MASTER_CASTERS_BOW = 18145, GUN_OF_TRIALS = 18146, @@ -6889,47 +6946,92 @@ xi.item = BIBIKI_SEASHELL = 18257, THROWING_TOMAHAWK = 18258, ANGON = 18259, + RELIC_KNUCKLES = 18260, + MILITANT_KNUCKLES = 18261, + DYNAMIS_KNUCKLES = 18262, CAESTUS = 18263, SPHARAI_75 = 18264, SPHARAI_80 = 18265, + RELIC_DAGGER = 18266, + MALEFIC_DAGGER = 18267, + DYNAMIS_DAGGER = 18268, BATARDEAU = 18269, MANDAU_75 = 18270, MANDAU_80 = 18271, + RELIC_SWORD = 18272, + GLYPTIC_SWORD = 18273, + DYNAMIS_SWORD = 18274, CALIBURN = 18275, EXCALIBUR_75 = 18276, EXCALIBUR_80 = 18277, + RELIC_BLADE = 18278, + GILDED_BLADE = 18279, + DYNAMIS_BLADE = 18280, VALHALLA = 18281, RAGNAROK_75 = 18282, RAGNAROK_80 = 18283, + RELIC_AXE = 18284, + LEONINE_AXE = 18285, + DYNAMIS_AXE = 18286, OGRE_KILLER = 18287, GUTTLER_75 = 18288, GUTTLER_80 = 18289, + RELIC_BHUJ = 18290, + AGONAL_BHUJ = 18291, + DYNAMIS_BHUJ = 18292, ABADDON_KILLER = 18293, BRAVURA_75 = 18294, BRAVURA_80 = 18295, + RELIC_LANCE = 18296, + HOTSPUR_LANCE = 18297, + DYNAMIS_LANCE = 18298, GAE_ASSAIL = 18299, GUNGNIR_75 = 18300, GUNGNIR_80 = 18301, + RELIC_SCYTHE = 18302, + MEMENTO_SCYTHE = 18303, + DYNAMIS_SCYTHE = 18304, BEC_DE_FAUCON = 18305, APOCALYPSE_75 = 18306, APOCALYPSE_80 = 18307, + IHINTANTO = 18308, + MIMIZUKU = 18309, + ROGETSU = 18310, YOSHIMITSU = 18311, KIKOKU_75 = 18312, KIKOKU_80 = 18313, + ITO = 18314, + HAYATEMARU = 18315, + OBOROMARU = 18316, TOTSUKANOTSURUGI = 18317, AMANOMURAKUMO_75 = 18318, AMANOMURAKUMO_80 = 18319, + RELIC_MAUL = 18320, + BATTERING_MAUL = 18321, + DYNAMIS_MAUL = 18322, GULLINTANI = 18323, MJOLLNIR_75 = 18324, MJOLLNIR_80 = 18325, + RELIC_STAFF = 18326, + SAGES_STAFF = 18327, + DYNAMIS_STAFF = 18328, THYRUS = 18329, CLAUSTRUM_75 = 18330, CLAUSTRUM_80 = 18331, + RELIC_GUN = 18332, + MARKSMANS_GUN = 18333, + DYNAMIS_GUN = 18334, FERDINAND = 18335, ANNIHILATOR_75 = 18336, ANNIHILATOR_80 = 18337, + RELIC_HORN = 18338, + PYRRHIC_HORN = 18339, + DYNAMIS_HORN = 18340, MILLENNIUM_HORN = 18341, GJALLARHORN_75 = 18342, + RELIC_BOW = 18344, + WOLVER_BOW = 18345, + DYNAMIS_BOW = 18346, FUTATOKOROTO = 18347, YOICHINOYUMI_75 = 18348, YOICHINOYUMI_80 = 18349, diff --git a/scripts/enum/mod.lua b/scripts/enum/mod.lua index c105f46a5e8..cc7a16d77ac 100644 --- a/scripts/enum/mod.lua +++ b/scripts/enum/mod.lua @@ -369,6 +369,7 @@ xi.mod = SUBTLE_BLOW = 289, SUBTLE_BLOW_II = 973, -- Subtle Blow II Effect (Cap 50%) Total Effect (SB + SB_II cap 75%) ENF_MAG_POTENCY = 290, -- Increases Enfeebling magic potency % + ENF_MAG_DURATION = 1151, -- Increases enfeebling magic duration % COUNTER = 291, KICK_ATTACK_RATE = 292, AFFLATUS_SOLACE = 293, @@ -506,10 +507,12 @@ xi.mod = ENHANCES_ABSORB_EFFECTS = 1136, -- Absorb Spell duration +x seconds (Enhances "Absorb" effects) AUGMENTS_ABSORB = 1137, -- Non-Liberator Absorb Spell potency +x% (Augments "Absorb" effects) ABSORB_EFFECT_DURATION = 1138, -- Absorb Spell duration +% ("Absorb" effect duration +x%) + AUGMENTS_ABSORB_TP = 1153, -- Increases absorb-TP potency, stacks with AUGMENTS_ABSORB -- Beastmaster TANDEM_STRIKE_POWER = 271, -- Grants a bonus to your and your pet's accuracy and magic accuracy when you and your pet are attacking the same target. TANDEM_BLOW_POWER = 272, -- Reduces amount of TP gained by enemies when striking them if you and your pet are attacking the same target. + ENHANCES_MONSTER_CORRELATION = 1155, -- Grants acc +X and attp +X% against a weaker opposing ecosystem. Typically applied to pet, not owner (item_mods_pet.sql) -- Samurai SENGIKORI_SC_DMG_DEBUFF = 1088, -- % Increase to closing skillchain damage. Applied to defender. @@ -697,7 +700,7 @@ xi.mod = SONG_DURATION_BONUS = 454, -- SONG_SPELLCASTING_TIME = 455, -- - AVATARS_FAVOR_ENHANCE = 141, -- Adds 1 rank to avatars favor + AVATARS_FAVOR_ENHANCE = 1154, -- Adds 1 rank to avatars favor QUICK_DRAW_DMG = 411, -- QUICK_DRAW_MACC = 191, -- Quick draw magic accuracy @@ -1052,9 +1055,7 @@ xi.mod = PARRY_HP_RECOVERY = 1135, -- Recover HP on successful parry. -- TODO: These mods are not yet implemented. - ENF_MAG_DURATION = 1151, -- TODO: Increase enfeebling spell duration (percent) REWARD_RECAST = 1152, -- TODO: Reduces Reward recast time (seconds) - AUGMENTS_ABSORB_TP = 1153, -- TODO: Increases absorb-TP potency, stacks with AUGMENTS_ABSORB -- IF YOU ADD ANY NEW MODIFIER HERE, ADD IT IN src/map/modifier.h ASWELL! diff --git a/scripts/enum/vana_time.lua b/scripts/enum/vana_time.lua index 232d19acd68..018e66b6722 100644 --- a/scripts/enum/vana_time.lua +++ b/scripts/enum/vana_time.lua @@ -2,14 +2,14 @@ xi = xi or {} -- Number of earth seconds for each Vana'diel time interval. -- See: https://www.bg-wiki.com/ffxi/Vana%27diel_Time -local secondsPerTick = 2.4 ---@enum xi.vanaTime xi.vanaTime = { - YEAR = 518400 * secondsPerTick, - MONTH = 43200 * secondsPerTick, - WEEK = 11520 * secondsPerTick, - DAY = 1440 * secondsPerTick, - HOUR = 60 * secondsPerTick, + YEAR = 360 * (24 * 60 * 2.4), -- 1244160 Earth seconds + MONTH = 30 * (24 * 60 * 2.4), -- 103680 Earth seconds + WEEK = 8 * (24 * 60 * 2.4), -- 27648 Earth seconds + DAY = 24 * (60 * 2.4), -- 3456 Earth seconds + HOUR = 60 * (2.4), -- 144 Earth seconds + MINUTE = 2.4, -- 2.4 Earth seconds } diff --git a/scripts/globals/combat/physical_utilities.lua b/scripts/globals/combat/physical_utilities.lua index 9dbcdbd2ef5..141a14adf18 100644 --- a/scripts/globals/combat/physical_utilities.lua +++ b/scripts/globals/combat/physical_utilities.lua @@ -234,7 +234,11 @@ end -- TP factor equation. Used to determine TP modifer across all cases of 'X varies with TP' xi.combat.physical.calculateTPfactor = function(actorTP, tpModifierTable) - local tpFactor = 0 + if not tpModifierTable then + return 0 + end + + local tpFactor = tpModifierTable[1] -- Assume this will be used for monstrosity fixed TP moved someday. if actorTP >= 2000 then tpFactor = tpModifierTable[2] + (actorTP - 2000) * (tpModifierTable[3] - tpModifierTable[2]) / 1000 @@ -246,15 +250,12 @@ xi.combat.physical.calculateTPfactor = function(actorTP, tpModifierTable) end -- TP Multiplier calculations. -xi.combat.physical.calculateFTP = function(actor, tpFactor) - ------------------------------ - -- Regular fTP - ------------------------------ - local fTP = tpFactor +xi.combat.physical.calculateFTPBonus = function(actor) + local fTPBonus = 0 -- Early return: Gear bonuses only come from gear. if actor:getObjType() ~= xi.objType.PC then - return fTP + return fTPBonus end -- Early return: Gear bonuses only apply to weaponskills with elemental properties. @@ -264,12 +265,10 @@ xi.combat.physical.calculateFTP = function(actor, tpFactor) scProp2 == xi.skillchainType.NONE and scProp3 == xi.skillchainType.NONE then - return fTP + return fTPBonus end - ------------------------------ - -- fTP bonuses. - ------------------------------ + -- fTP bonuses from gear. local dayElement = VanadielDayElement() for elementChecked = xi.element.FIRE, xi.element.DARK do @@ -278,17 +277,17 @@ xi.combat.physical.calculateFTP = function(actor, tpFactor) wsElementalProperties[scProp2][elementChecked] == 1 or wsElementalProperties[scProp3][elementChecked] == 1 then - fTP = fTP + actor:getMod(xi.combat.element.getElementalFTPModifier(elementChecked)) / 256 + fTPBonus = fTPBonus + actor:getMod(xi.combat.element.getElementalFTPModifier(elementChecked)) / 256 if dayElement == elementChecked then - fTP = fTP + actor:getMod(xi.mod.DAY_FTP_BONUS) / 256 + fTPBonus = fTPBonus + actor:getMod(xi.mod.DAY_FTP_BONUS) / 256 end end end - fTP = fTP + actor:getMod(xi.mod.ANY_FTP_BONUS) / 256 + fTPBonus = fTPBonus + actor:getMod(xi.mod.ANY_FTP_BONUS) / 256 - return fTP + return fTPBonus end -- WARNING: This function is used in src/utils/battleutils.cpp "GetDamageRatio" function. diff --git a/scripts/globals/common.lua b/scripts/globals/common.lua index 20e37a9537e..5bdecfe80d6 100644 --- a/scripts/globals/common.lua +++ b/scripts/globals/common.lua @@ -60,11 +60,12 @@ getMidnight = JstMidnight ----------------------------------- function getVanaMidnight(day) - local curtime = os.time() + local curtime = os.time() + local secondsToMidnight = xi.vanaTime.DAY - (VanadielTime() % xi.vanaTime.DAY) + if day ~= nil then - curtime = curtime + 24 * 144 * day + secondsToMidnight = secondsToMidnight + (day * xi.vanaTime.DAY) end - local finaltime = curtime + (23 - VanadielHour()) * 144 + (60 - VanadielMinute()) * 2.4 - return finaltime + return curtime + secondsToMidnight end diff --git a/scripts/globals/mobs.lua b/scripts/globals/mobs.lua index ab88d87f7b1..53f2870ae72 100644 --- a/scripts/globals/mobs.lua +++ b/scripts/globals/mobs.lua @@ -96,12 +96,8 @@ xi.mob.phOnDespawn = function(ph, phList, chance, cooldown, params) not lotteryPrimed(phList) and math.random(1, 1000) <= chance then - local nextRepopTime = os.time() + GetMobRespawnTime(phId) - -- That's earth time, subtract SE epoch to get Vanatime - nextRepopTime = nextRepopTime - 1009810800 - -- The enum bakes in a multiplication of 2.4, gotta reverse that to get accurate hour - local nextRepopDate = (nextRepopTime / 60 * 25) + 886 * (xi.vanaTime.YEAR / 2.4) - local nextRepopHour = (nextRepopDate % (xi.vanaTime.DAY / 2.4)) / (xi.vanaTime.HOUR / 2.4) + local nextRepopTime = VanadielTime() + GetMobRespawnTime(phId) + local nextRepopHour = math.floor((nextRepopTime % xi.vanaTime.DAY) / xi.vanaTime.HOUR) -- If the NM is day only and spawn would happen during the night, bail out if params.dayOnly and diff --git a/scripts/globals/spells/absorb_spell.lua b/scripts/globals/spells/absorb_spell.lua index 243dc9bd216..f3f6319b960 100644 --- a/scripts/globals/spells/absorb_spell.lua +++ b/scripts/globals/spells/absorb_spell.lua @@ -216,6 +216,7 @@ xi.spells.absorb.doAbsorbTPSpell = function(caster, target, spell) local elementalStaffBonus = xi.spells.damage.calculateElementalStaffBonus(caster, xi.element.DARK) local dayAndWeather = xi.spells.damage.calculateDayAndWeather(caster, xi.element.DARK, false) local absorbMultiplier = 1 + caster:getMod(xi.mod.AUGMENTS_ABSORB) / 100 + local absorbTpMultiplier = 1 + caster:getMod(xi.mod.AUGMENTS_ABSORB_TP) / 100 -- TODO: Additive with aug abs or multiplicative? local liberatorMultiplier = 1 + caster:getMod(xi.mod.AUGMENTS_ABSORB_LIBERATOR) / 100 -- Operations. @@ -225,6 +226,7 @@ xi.spells.absorb.doAbsorbTPSpell = function(caster, target, spell) finalDamage = math.floor(finalDamage * elementalStaffBonus) finalDamage = math.floor(finalDamage * dayAndWeather) finalDamage = math.floor(finalDamage * absorbMultiplier) + finalDamage = math.floor(finalDamage * absorbTpMultiplier) finalDamage = math.floor(finalDamage * liberatorMultiplier) -- Clamp diff --git a/scripts/globals/spells/enfeebling_spell.lua b/scripts/globals/spells/enfeebling_spell.lua index 9f8a2690548..2c775d73c6c 100644 --- a/scripts/globals/spells/enfeebling_spell.lua +++ b/scripts/globals/spells/enfeebling_spell.lua @@ -324,6 +324,8 @@ xi.spells.enfeebling.calculateDuration = function(caster, target, spellId, spell duration = duration + caster:getJobPointLevel(xi.jp.STYMIE_EFFECT) end end + + duration = math.floor(duration * (1 + caster:getMod(xi.mod.ENF_MAG_DURATION) / 100)) end ---@cast duration integer diff --git a/scripts/globals/weaponskills.lua b/scripts/globals/weaponskills.lua index 0170033adce..2869b1e4cb5 100644 --- a/scripts/globals/weaponskills.lua +++ b/scripts/globals/weaponskills.lua @@ -659,7 +659,8 @@ end -- damage is returned, handles reductions based on target resistances and passes off to xi.weaponskills.takeWeaponskillDamage. xi.weaponskills.doPhysicalWeaponskill = function(attacker, target, wsID, wsParams, tp, action, primaryMsg, taChar) -- Set up conditions and wsParams used for calculating weaponskill damage - local gorgetBeltFTP, gorgetBeltAcc = xi.weaponskills.handleWSGorgetBelt(attacker) + local gearFTP = xi.combat.physical.calculateFTPBonus(attacker) + local gearAcc = math.floor(gearFTP * 10) local attack = { ['type'] = xi.attackType.PHYSICAL, @@ -696,8 +697,8 @@ xi.weaponskills.doPhysicalWeaponskill = function(attacker, target, wsID, wsParam calcParams.bonusAcc = attacker:getMod(xi.mod.JUMP_ACC_BONUS) calcParams.bonusWSmods = 0 else - calcParams.bonusfTP = gorgetBeltFTP or 0 - calcParams.bonusAcc = (gorgetBeltAcc or 0) + attacker:getMod(xi.mod.WSACC) + calcParams.bonusfTP = gearFTP + calcParams.bonusAcc = gearAcc + attacker:getMod(xi.mod.WSACC) calcParams.bonusWSmods = wsParams.bonusWSmods or 0 end @@ -737,7 +738,9 @@ end -- damage is returned, handles reductions based on target resistances and passes off to xi.weaponskills.takeWeaponskillDamage. xi.weaponskills.doRangedWeaponskill = function(attacker, target, wsID, wsParams, tp, action, primaryMsg) -- Set up conditions and params used for calculating weaponskill damage - local gorgetBeltFTP, gorgetBeltAcc = xi.weaponskills.handleWSGorgetBelt(attacker) + local gearFTP = xi.combat.physical.calculateFTPBonus(attacker) + local gearAcc = math.floor(gearFTP * 10) + local attack = { ['type'] = xi.attackType.RANGED, @@ -765,8 +768,8 @@ xi.weaponskills.doRangedWeaponskill = function(attacker, target, wsID, wsParams, flourishEffect = false, tpUsed = tp, bonusTP = wsParams.bonusTP or 0, - bonusfTP = gorgetBeltFTP or 0, - bonusAcc = (gorgetBeltAcc or 0) + attacker:getMod(xi.mod.WSACC), + bonusfTP = gearFTP, + bonusAcc = gearAcc + attacker:getMod(xi.mod.WSACC), bonusWSmods = wsParams.bonusWSmods or 0, attackType = xi.attackType.RANGED } @@ -831,11 +834,10 @@ xi.weaponskills.doMagicWeaponskill = function(attacker, target, wsID, wsParams, ['wsID'] = wsID } - local bonusfTP, bonusacc = xi.weaponskills.handleWSGorgetBelt(attacker) - bonusacc = bonusacc + attacker:getMod(xi.mod.WSACC) - - local fint = utils.clamp(8 + attacker:getStat(xi.mod.INT) - target:getStat(xi.mod.INT), -32, 32) - local dmg = 0 + local gearFTP = xi.combat.physical.calculateFTPBonus(attacker) + local gearAcc = math.floor(gearFTP * 10) + attacker:getMod(xi.mod.WSACC) + local fint = utils.clamp(8 + attacker:getStat(xi.mod.INT) - target:getStat(xi.mod.INT), -32, 32) + local dmg = 0 -- Magic-based WSes never miss, so we don't need to worry about calculating a miss, only if a shadow absorbed it. if not shadowAbsorb(target) then @@ -843,7 +845,7 @@ xi.weaponskills.doMagicWeaponskill = function(attacker, target, wsID, wsParams, dmg = dmg + attacker:getMainLvl() + 2 + fint -- Applying fTP multiplier - local ftp = xi.weaponskills.fTP(tp, wsParams.ftpMod) + bonusfTP + local ftp = xi.weaponskills.fTP(tp, wsParams.ftpMod) + gearFTP dmg = dmg * ftp @@ -867,7 +869,7 @@ xi.weaponskills.doMagicWeaponskill = function(attacker, target, wsID, wsParams, -- Calculate magical bonuses and reductions dmg = math.floor(addBonusesAbility(attacker, wsParams.ele, target, dmg, wsParams)) - dmg = math.floor(dmg * applyResistanceAbility(attacker, target, wsParams.ele, wsParams.skill, bonusacc)) + dmg = math.floor(dmg * applyResistanceAbility(attacker, target, wsParams.ele, wsParams.skill, gearAcc)) dmg = math.floor(dmg * xi.spells.damage.calculateTMDA(target, wsParams.ele)) if dmg < 0 then @@ -1108,93 +1110,6 @@ xi.weaponskills.calculatedIgnoredDef = function(tp, def, ignoredDefenseTable) return 0 end -xi.weaponskills.handleWSGorgetBelt = function(attacker) - local ftpBonus = 0 - local accBonus = 0 - - if attacker:getObjType() == xi.objType.PC then - local elementalGorget = -- Ordered by element correctly. TODO: mods/latents instead of items - { - xi.item.FLAME_GORGET, - xi.item.SNOW_GORGET, - xi.item.BREEZE_GORGET, - xi.item.SOIL_GORGET, - xi.item.THUNDER_GORGET, - xi.item.AQUA_GORGET, - xi.item.LIGHT_GORGET, - xi.item.SHADOW_GORGET - } - - local elementalBelt = -- Ordered by element correctly. TODO: mods/latents instead of items - { - xi.item.FLAME_BELT, - xi.item.SNOW_BELT, - xi.item.BREEZE_BELT, - xi.item.SOIL_BELT, - xi.item.THUNDER_BELT, - xi.item.AQUA_BELT, - xi.item.LIGHT_BELT, - xi.item.SHADOW_BELT - } - - local neck = attacker:getEquipID(xi.slot.NECK) - local belt = attacker:getEquipID(xi.slot.WAIST) - local weapon = attacker:getEquipID(xi.slot.MAIN) - local scProp1, scProp2, scProp3 = attacker:getWSSkillchainProp() - - for i, v in ipairs(elementalGorget) do - if neck == v then - if - xi.magicburst.doesElementMatchWeaponskill(i, scProp1) or - xi.magicburst.doesElementMatchWeaponskill(i, scProp2) or - xi.magicburst.doesElementMatchWeaponskill(i, scProp3) - then - accBonus = accBonus + 10 - ftpBonus = ftpBonus + 0.1 - end - - break - end - end - - if neck == xi.item.FOTIA_GORGET then -- Fotia Gorget - accBonus = accBonus + 10 - ftpBonus = ftpBonus + 0.1 - end - - for i, v in ipairs(elementalBelt) do - if belt == v then - if - xi.magicburst.doesElementMatchWeaponskill(i, scProp1) or - xi.magicburst.doesElementMatchWeaponskill(i, scProp2) or - xi.magicburst.doesElementMatchWeaponskill(i, scProp3) - then - accBonus = accBonus + 10 - ftpBonus = ftpBonus + 0.1 - end - - break - end - end - - if belt == xi.item.FOTIA_BELT then -- Fotia Belt - accBonus = accBonus + 10 - ftpBonus = ftpBonus + 0.1 - end - - if - weapon == xi.item.PRESTER and - (xi.magicburst.doesElementMatchWeaponskill(xi.element.WIND, scProp1) or - xi.magicburst.doesElementMatchWeaponskill(xi.element.WIND, scProp2) or - xi.magicburst.doesElementMatchWeaponskill(xi.element.WIND, scProp3)) - then -- Prester - ftpBonus = ftpBonus + 0.1 - end - end - - return ftpBonus, accBonus -end - xi.weaponskills.handleWeaponskillEffect = function(actor, target, effectId, actionElement, damage, power, duration) if damage > 0 and diff --git a/scripts/globals/znm.lua b/scripts/globals/znm.lua index 3b3afd2d512..5ba9788460b 100644 --- a/scripts/globals/znm.lua +++ b/scripts/globals/znm.lua @@ -185,7 +185,7 @@ xi.znm.soultrapper = xi.znm.soultrapper or {} -- onItemCheck ----------------------------------- -xi.znm.soultrapper.onItemCheck = function(target, item, player, caster) +xi.znm.soultrapper.onItemCheck = function(target, item, param, caster) -- can not be used on non mobs or Structure type mobs if not target:isMob() or @@ -195,16 +195,16 @@ xi.znm.soultrapper.onItemCheck = function(target, item, player, caster) end if - player:hasStatusEffect(xi.effect.INVISIBLE) or - player:hasStatusEffect(xi.effect.SNEAK) or - player:hasStatusEffect(xi.effect.DEODORIZE) or - player:hasStatusEffect(xi.effect.HIDE) or - player:hasStatusEffect(xi.effect.CAMOUFLAGE) + caster:hasStatusEffect(xi.effect.INVISIBLE) or + caster:hasStatusEffect(xi.effect.SNEAK) or + caster:hasStatusEffect(xi.effect.DEODORIZE) or + caster:hasStatusEffect(xi.effect.HIDE) or + caster:hasStatusEffect(xi.effect.CAMOUFLAGE) then - return xi.msg.basic.ITEM_NO_USE_SNEAK, player:getEquipID(xi.slot.RANGED) + return xi.msg.basic.ITEM_NO_USE_SNEAK, caster:getEquipID(xi.slot.RANGED) end - local id = player:getEquipID(xi.slot.AMMO) + local id = caster:getEquipID(xi.slot.AMMO) if id ~= xi.item.BLANK_SOUL_PLATE and id ~= xi.item.BLANK_HIGH_SPEED_SOUL_PLATE @@ -212,7 +212,7 @@ xi.znm.soultrapper.onItemCheck = function(target, item, player, caster) return xi.msg.basic.ITEM_NO_ITEMS_EQUIPPED end - if player:getFreeSlotsCount() == 0 then + if caster:getFreeSlotsCount() == 0 then return xi.msg.basic.FULL_INVENTORY end @@ -223,7 +223,7 @@ end -- onItemUse ----------------------------------- -xi.znm.soultrapper.onItemUse = function(target, item, player) +xi.znm.soultrapper.onItemUse = function(target, player, item) -- Soul plate not guaranteed -- to validate long term: some posts hint at level correction on success rate vs. higher level mobs. if math.random(100) > xi.znm.SOULTRAPPER_SUCCESS * xi.znm.SOULPLATE_HS_MULT then @@ -382,7 +382,7 @@ end ----------------------------------- xi.znm.ryo.onEventUpdate = function(player, csid, option, npc) - if csid == 914 then -- Get approximate value of traded soulplate + if csid == 914 then -- Get approximate value of traded soulplate local zeniValue = xi.znm.ryo.tradedPlateValue(player) xi.znm.ryo.setTradedPlateValue(player, 0) @@ -485,7 +485,7 @@ xi.znm.sanraku.handleTradeWithPlate = function(player, npc, item) end xi.znm.sanraku.platesTradedToday = function(player) - local currentDay = VanadielYear() * 360 + VanadielDayOfTheYear() + local currentDay = VanadielUniqueDay() local storedDay = xi.znm.playerTradingDay(player) if currentDay ~= storedDay then @@ -666,7 +666,7 @@ end xi.znm.sanraku.handleCompletedTradeWithPlate = function(player) player:tradeComplete() - xi.znm.setPlayerTradingDay(player, VanadielYear() * 360 + VanadielDayOfTheYear()) + xi.znm.setPlayerTradingDay(player, VanadielUniqueDay()) xi.znm.incrementTradedPlates(player) local zeniValue = xi.znm.sanraku.tradedPlateValue(player) @@ -713,7 +713,7 @@ xi.znm.getPopPrice = function(mob, znmTier) popCost == nil or popCost == 0 then - popCost = xi.znm.ZNM_popCostS[znmTier].minPrice + popCost = xi.znm.ZNM_POP_COSTS[znmTier].minPrice SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost) end @@ -723,8 +723,8 @@ end -- pop prices update per purchase at the mob level xi.znm.updatePopPrice = function(mob, znmTier) if not xi.znm.ZNM_STATIC_POP_PRICES then - local popCost = math.min(xi.znm.getPopPrice(mob, znmTier) + xi.znm.ZNM_popCostS[znmTier].addedPrice, - xi.znm.ZNM_popCostS[znmTier].maxPrice) + local popCost = math.min(xi.znm.getPopPrice(mob, znmTier) + xi.znm.ZNM_POP_COSTS[znmTier].addedPrice, + xi.znm.ZNM_POP_COSTS[znmTier].maxPrice) SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost) end end @@ -739,8 +739,8 @@ xi.znm.ZNMPopPriceDecay = function() for i = 1, 31 do mob = xi.znm.POP_ITEMS[i].mob znmTier = xi.znm.POP_ITEMS[i].tier - popCost = math.max(xi.znm.getPopPrice(mob, znmTier) - xi.znm.ZNM_popCostS[znmTier].decayPrice, - xi.znm.ZNM_popCostS[znmTier].minPrice) + popCost = math.max(xi.znm.getPopPrice(mob, znmTier) - xi.znm.ZNM_POP_COSTS[znmTier].decayPrice, + xi.znm.ZNM_POP_COSTS[znmTier].minPrice) SetServerVariable('[ZNM][' .. mob .. ']PopCost', popCost) end @@ -772,7 +772,7 @@ xi.znm.numberOfTradedPlates = function(player) end xi.znm.incrementTradedPlates = function(player) - player:addVar('[ZNM][Sanraku]TradedPlates', 1) + player:incrementCharVar('[ZNM][Sanraku]TradedPlates', 1) end xi.znm.resetDailyTrackingVars = function(player) diff --git a/scripts/globals/znm_data.lua b/scripts/globals/znm_data.lua index b019eff5dde..54657235faa 100644 --- a/scripts/globals/znm_data.lua +++ b/scripts/globals/znm_data.lua @@ -220,70 +220,74 @@ xi.znm.TROPHIES = xi.znm.POP_ITEMS = { -- Ordered to match the csid options - -- { popitemID, ZNMtier (for pop price updating), seals_to_remove} - { item = xi.item.HELLCAGE_BUTTERFLY, tier = 1, seal = 0 }, -- Vulpangue - { item = xi.item.JUG_OF_FLORAL_NECTAR, tier = 1, seal = 0 }, -- Chamrosh - { item = xi.item.WEDGE_OF_RODENT_CHEESE, tier = 1, seal = 0 }, -- Cheese Hoarder Gigiroon - { item = xi.item.BUNCH_OF_SENORITA_PAMAMAS, tier = 2, seal = xi.keyItem.MAROON_SEAL }, -- Iriz Ima - { item = xi.item.JAR_OF_OILY_BLOOD, tier = 2, seal = xi.keyItem.MAROON_SEAL }, -- Lividroot Amooshah - { item = xi.item.STRAND_OF_SAMARIRI_CORPSEHAIR, tier = 2, seal = xi.keyItem.MAROON_SEAL }, -- Iriri Samariri - { item = xi.item.BAR_OF_FERRITE, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, -- Armed Gear - { item = xi.item.BAGGED_SHEEP_BOTFLY, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, -- Gotoh Zha the Redolent - { item = xi.item.OLZHIRYAN_CACTUS_PADDLE, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, -- Dea + -- { mob, popitemID, ZNMtier (for pop price updating), seals_to_remove} + { mob = 'Vulpangue', item = xi.item.HELLCAGE_BUTTERFLY, tier = 1, seal = 0 }, + { mob = 'Chamrosh', item = xi.item.JUG_OF_FLORAL_NECTAR, tier = 1, seal = 0 }, + { mob = 'Cheese Hoarder Gigiroon', item = xi.item.WEDGE_OF_RODENT_CHEESE, tier = 1, seal = 0 }, + { mob = 'Iriz Ima', item = xi.item.BUNCH_OF_SENORITA_PAMAMAS, tier = 2, seal = xi.keyItem.MAROON_SEAL }, + { mob = 'Lividroot Amooshah', item = xi.item.JAR_OF_OILY_BLOOD, tier = 2, seal = xi.keyItem.MAROON_SEAL }, + { mob = 'Iriri Samariri', item = xi.item.STRAND_OF_SAMARIRI_CORPSEHAIR, tier = 2, seal = xi.keyItem.MAROON_SEAL }, + { mob = 'Armed Gear', item = xi.item.BAR_OF_FERRITE, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, + { mob = 'Gotoh Zha the Redolent', item = xi.item.BAGGED_SHEEP_BOTFLY, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, + { mob = 'Dea', item = xi.item.OLZHIRYAN_CACTUS_PADDLE, tier = 3, seal = xi.keyItem.APPLE_GREEN_SEAL }, { + mob = 'Tinnin', item = xi.item.JUG_OF_MONKEY_WINE, tier = 4, seal = { - xi.keyItem.CHARCOAL_GREY_SEAL, -- Tinnin + xi.keyItem.CHARCOAL_GREY_SEAL, xi.keyItem.DEEP_PURPLE_SEAL, xi.keyItem.CHESTNUT_COLORED_SEAL, }, }, - { item = xi.item.CLUMP_OF_SHADELEAVES, tier = 1, seal = 0 }, -- Brass Borer - { item = xi.item.BEAKER_OF_PECTIN, tier = 1, seal = 0 }, -- Claret - { item = xi.item.FLASK_OF_COG_LUBRICANT, tier = 1, seal = 0 }, -- Ob - { item = xi.item.SLAB_OF_RAW_BUFFALO, tier = 2, seal = xi.keyItem.CERISE_SEAL }, -- Anantaboga - { item = xi.item.LUMP_OF_BONE_CHARCOAL, tier = 2, seal = xi.keyItem.CERISE_SEAL }, -- Reacton - { item = xi.item.PINCH_OF_GRANULATED_SUGAR, tier = 2, seal = xi.keyItem.CERISE_SEAL }, -- Dextrose - { item = xi.item.VIAL_OF_PURE_BLOOD, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, -- Nosferatu - { item = xi.item.VINEGAR_PIE, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, -- Khromasoul Bhurborlor - { item = xi.item.JAR_OF_ROCK_JUICE, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, -- Achamoth + { mob = 'Brass Borer', item = xi.item.CLUMP_OF_SHADELEAVES, tier = 1, seal = 0 }, + { mob = 'Claret', item = xi.item.BEAKER_OF_PECTIN, tier = 1, seal = 0 }, + { mob = 'Ob', item = xi.item.FLASK_OF_COG_LUBRICANT, tier = 1, seal = 0 }, + { mob = 'Anantaboga', item = xi.item.SLAB_OF_RAW_BUFFALO, tier = 2, seal = xi.keyItem.CERISE_SEAL }, + { mob = 'Reacton', item = xi.item.LUMP_OF_BONE_CHARCOAL, tier = 2, seal = xi.keyItem.CERISE_SEAL }, + { mob = 'Dextrose', item = xi.item.PINCH_OF_GRANULATED_SUGAR, tier = 2, seal = xi.keyItem.CERISE_SEAL }, + { mob = 'Nosferatu', item = xi.item.VIAL_OF_PURE_BLOOD, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, + { mob = 'Khromasoul Bhurborlor', item = xi.item.VINEGAR_PIE, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, + { mob = 'Achamoth', item = xi.item.JAR_OF_ROCK_JUICE, tier = 3, seal = xi.keyItem.SALMON_COLORED_SEAL }, { + mob = 'Sarameya', item = xi.item.CHUNK_OF_BUFFALO_CORPSE, tier = 4, seal = { - xi.keyItem.COPPER_COLORED_SEAL, -- Sarameya + xi.keyItem.COPPER_COLORED_SEAL, xi.keyItem.GOLD_COLORED_SEAL, xi.keyItem.PURPLISH_GREY_SEAL, }, }, - { item = xi.item.GOLDEN_TEETH, tier = 1, seal = 0 }, -- Velionis - { item = xi.item.GREENLING, tier = 1, seal = 0 }, -- Lil' Apkallu - { item = xi.item.BOTTLE_OF_SPOILT_BLOOD, tier = 1, seal = 0 }, -- Chigre - { item = xi.item.OPALUS_GEM, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, -- Wulgaru - { item = xi.item.MERROW_NO_11_MOLTING, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, -- Zareehkl the Jubilant - { item = xi.item.MINT_DROP, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, -- Verdelet - { item = xi.item.BOUND_EXORCISM_TREATISE, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, -- Mahjlaef the Paintorn - { item = xi.item.CLUMP_OF_MYRRH, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, -- Experimental Lamia - { item = xi.item.WHOLE_ROSE_SCAMPI, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, -- Nuhn + { mob = 'Velionis', item = xi.item.GOLDEN_TEETH, tier = 1, seal = 0 }, + { mob = 'Lil\' Apkallu', item = xi.item.GREENLING, tier = 1, seal = 0 }, + { mob = 'Chigre', item = xi.item.BOTTLE_OF_SPOILT_BLOOD, tier = 1, seal = 0 }, + { mob = 'Wulgaru', item = xi.item.OPALUS_GEM, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, + { mob = 'Zareehkl the Jubilant', item = xi.item.MERROW_NO_11_MOLTING, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, + { mob = 'Verdelet', item = xi.item.MINT_DROP, tier = 2, seal = xi.keyItem.PINE_GREEN_SEAL }, + { mob = 'Mahjlaef the Paintorn', item = xi.item.BOUND_EXORCISM_TREATISE, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, + { mob = 'Experimental Lamia', item = xi.item.CLUMP_OF_MYRRH, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, + { mob = 'Nuhn', item = xi.item.WHOLE_ROSE_SCAMPI, tier = 3, seal = xi.keyItem.AMBER_COLORED_SEAL }, { + mob = 'Tyger', item = xi.item.CHUNK_OF_SINGED_BUFFALO, tier = 4, seal = { - xi.keyItem.TAUPE_COLORED_SEAL, -- Tyger + xi.keyItem.TAUPE_COLORED_SEAL, xi.keyItem.FALLOW_COLORED_SEAL, xi.keyItem.SIENNA_COLORED_SEAL, }, }, { + mob = 'Pandemonium Warden', item = xi.item.PANDEMONIUM_KEY, tier = 5, seal = { - xi.keyItem.LILAC_COLORED_SEAL, -- Pandemonium Warden + xi.keyItem.LILAC_COLORED_SEAL, xi.keyItem.LAVENDER_COLORED_SEAL, xi.keyItem.BRIGHT_BLUE_SEAL, }, diff --git a/scripts/missions/windurst/2_2_A_Testing_Time.lua b/scripts/missions/windurst/2_2_A_Testing_Time.lua index eb08e4ed75e..35c853d6bcb 100644 --- a/scripts/missions/windurst/2_2_A_Testing_Time.lua +++ b/scripts/missions/windurst/2_2_A_Testing_Time.lua @@ -33,72 +33,44 @@ local killCounter = function(mob, player, optParams) end local assessment = function(player, npc) - local startTime = mission:getVar(player, 'StartTime') - local startDay = mission:getVar(player, 'StartDay') - local startHour = mission:getVar(player, 'StartHour') - local secondsPassed = os.time() - startTime - local hoursPassed = VanadielHour() - local killCount = mission:getVar(player, 'KillCount') - local completed = player:hasCompletedMission(mission.areaId, mission.missionId) + local currentTime = VanadielTime() + local endTime = mission:getVar(player, 'EndTime') + local killCount = mission:getVar(player, 'KillCount') + local completed = player:hasCompletedMission(mission.areaId, mission.missionId) -- player took too long to speak under requirements in time, so they fail mission - if - (not completed and secondsPassed > 3456) or - (completed and secondsPassed > 6912) - then + if currentTime > endTime then return mission:progressEvent(202) end - -- handle the events for first-time doing the mission - if not completed and secondsPassed > 3312 then - local event = 198 - - if killCount >= 35 then - event = 201 - elseif killCount >= 30 then - event = 200 - elseif killCount >= 19 then - event = 199 + -- player hasn't waited long enough to be assessed + if currentTime < endTime - xi.vanaTime.HOUR then + local hoursRemaining = math.ceil((endTime - currentTime) / xi.vanaTime.HOUR) + if completed then + return mission:progressEvent(204, 0, 0, 0, 0, 0, VanadielHour(), hoursRemaining, 0) + else + return mission:progressEvent(183, 0, VanadielHour(), hoursRemaining) end + end - return mission:progressEvent(event, 0, VanadielHour(), 1, killCount) - -- handle the events for repeating mission - elseif completed and secondsPassed > 6768 then - local event = 208 + -- handle the events for first-time doing the mission + if not completed then + local event = completed and 208 or 198 if killCount >= 35 then - event = 206 + event = completed and 206 or 201 elseif killCount >= 30 then - event = 209 + event = completed and 209 or 200 + elseif not completed and killCount >= 19 then + event = 199 end return mission:progressEvent(event, 0, VanadielHour(), 1, killCount) - -- player hasn't waited long enough to be assessed - else - if VanadielDayOfTheYear() == startDay then - hoursPassed = hoursPassed - startHour - elseif VanadielDayOfTheYear() == startDay + 1 then - hoursPassed = hoursPassed - startHour + 24 - else - if completed then - hoursPassed = (24 - startHour) + hoursPassed + 24 - else - hoursPassed = (24 - startHour) + hoursPassed - end - end - - if completed then - return mission:progressEvent(204, 0, 0, 0, 0, 0, VanadielHour(), 48 - hoursPassed, 0) - else - return mission:progressEvent(183, 0, VanadielHour(), 24 - hoursPassed) - end end end local failMission = function(player, csid, option, npc) - mission:setVar(player, 'StartDay', 0) - mission:setVar(player, 'StartHour', 0) - mission:setVar(player, 'StartTime', 0) + mission:setVar(player, 'EndTime', 0) mission:setVar(player, 'KillCount', 0) player:delKeyItem(xi.ki.CREATURE_COUNTER_MAGIC_DOLL) player:delMission(mission.areaId, mission.missionId) @@ -234,9 +206,7 @@ mission.sections = if option == 2 then player:setMissionStatus(mission.areaId, 2) npcUtil.giveKeyItem(player, xi.ki.CREATURE_COUNTER_MAGIC_DOLL) - mission:setVar(player, 'StartDay', VanadielDayOfTheYear()) - mission:setVar(player, 'StartHour', VanadielHour()) - mission:setVar(player, 'StartTime', os.time()) + mission:setVar(player, 'EndTime', VanadielTime() + xi.vanaTime.DAY) end end, @@ -244,9 +214,7 @@ mission.sections = if option == 2 then player:setMissionStatus(mission.areaId, 2) npcUtil.giveKeyItem(player, xi.ki.CREATURE_COUNTER_MAGIC_DOLL) - mission:setVar(player, 'StartDay', VanadielDayOfTheYear()) - mission:setVar(player, 'StartHour', VanadielHour()) - mission:setVar(player, 'StartTime', os.time()) + mission:setVar(player, 'EndTime', VanadielTime() + (2 * xi.vanaTime.DAY)) end end, }, diff --git a/scripts/quests/otherAreas/RQ2_Way_of_the_Cook.lua b/scripts/quests/otherAreas/RQ2_Way_of_the_Cook.lua index 60953d4b5be..dd8371ef07f 100644 --- a/scripts/quests/otherAreas/RQ2_Way_of_the_Cook.lua +++ b/scripts/quests/otherAreas/RQ2_Way_of_the_Cook.lua @@ -7,8 +7,6 @@ ----------------------------------- local quest = Quest:new(xi.questLog.OTHER_AREAS, xi.quest.id.otherAreas.WAY_OF_THE_COOK) -local daysPassed = 0 -local totalHoursLeft = 0 quest.reward = { @@ -32,7 +30,7 @@ quest.sections = { onTrigger = function(player, npc) if - player:getCharVar('Quest[4][0]DayCompleted') + 7 < VanadielUniqueDay() and + player:getCharVar('Quest[4][0]DayCompleted') + 8 <= VanadielUniqueDay() and player:getFameLevel(xi.fameArea.WINDURST) > 2 then return quest:progressEvent(76, xi.item.BEEHIVE_CHIP, xi.item.SLICE_OF_DHALMEL_MEAT) -- Way of the Cook starting event. @@ -48,9 +46,8 @@ quest.sections = { [76] = function(player, csid, option, npc) if option == 74 then -- Accept quest option. - player:setCharVar('Quest[4][0]DayCompleted', 0) -- Delete previous quest (Rycharde the Chef) variables - quest:setVar(player, 'HourStarted', VanadielHour()) -- Set current quest started variables - quest:setVar(player, 'DayStarted', VanadielDayOfTheYear()) -- Set current quest started variables + player:setCharVar('Quest[4][0]DayCompleted', 0) -- Delete previous quest (Rycharde the Chef) variables + quest:setVar(player, 'EndTime', VanadielTime() + (3 * xi.vanaTime.DAY)) -- Set current quest started variables quest:begin(player) end end, @@ -69,11 +66,12 @@ quest.sections = ['Rycharde'] = { onTrigger = function(player, npc) - daysPassed = VanadielDayOfTheYear() - quest:getVar(player, 'DayStarted') - totalHoursLeft = 72 - (VanadielHour() + daysPassed * 24) + quest:getVar(player, 'HourStarted') + local currentTime = VanadielTime() + local endTime = quest:getVar(player, 'EndTime') - if totalHoursLeft > 0 then - return quest:event(78, totalHoursLeft) -- You have x hours left. + if currentTime < endTime then + local hoursLeft = math.ceil((endTime - currentTime) / xi.vanaTime.HOUR) + return quest:event(78, hoursLeft) -- You have x hours left. else return quest:event(79) -- Not done yet. end @@ -81,10 +79,10 @@ quest.sections = onTrade = function(player, npc, trade) if npcUtil.tradeHasExactly(trade, { xi.item.SLICE_OF_DHALMEL_MEAT, xi.item.BEEHIVE_CHIP }) then - daysPassed = VanadielDayOfTheYear() - quest:getVar(player, 'DayStarted') - totalHoursLeft = 72 - (VanadielHour() + daysPassed * 24) + quest:getVar(player, 'HourStarted') + local currentTime = VanadielTime() + local endTime = quest:getVar(player, 'EndTime') - if totalHoursLeft > 0 then + if currentTime < endTime then return quest:progressEvent(80) -- Quest completed in time. else return quest:progressEvent(81) -- Quest completed late. diff --git a/scripts/quests/windurst/SOB4_Onion_Rings.lua b/scripts/quests/windurst/SOB4_Onion_Rings.lua index 530d76852ea..49cb8e4ff27 100644 --- a/scripts/quests/windurst/SOB4_Onion_Rings.lua +++ b/scripts/quests/windurst/SOB4_Onion_Rings.lua @@ -7,10 +7,10 @@ local quest = Quest:new(xi.questLog.WINDURST, xi.quest.id.windurst.ONION_RINGS) local function timedEvents(player, inTime, outATime) - local daysPassed = VanadielDayOfTheYear() - quest:getVar(player, 'DayStarted') - local totalHoursLeft = 24 - (VanadielHour() + daysPassed * 24) + quest:getVar(player, 'HourStarted') + local currentTime = VanadielTime() + local endTime = quest:getVar(player, 'EndTime') - if totalHoursLeft > 0 then + if currentTime < endTime then return quest:event(inTime) else return quest:event(outATime) @@ -48,11 +48,11 @@ quest.sections = not quest:getMustZone(player) then if player:hasKeyItem(xi.ki.OLD_RING) then - local daysPassed = VanadielDayOfTheYear() - quest:getVar(player, 'DayStarted') - local totalHoursLeft = 24 - (VanadielHour() + daysPassed * 24) + quest:getVar(player, 'HourStarted') + local currentTime = VanadielTime() + local endTime = quest:getVar(player, 'EndTime') if - totalHoursLeft > 0 and + currentTime < endTime and quest:getVar(player, 'Prog') == 1 then return quest:progressEvent(430, 0, xi.ki.OLD_RING) -- Quest starting event. @@ -73,8 +73,7 @@ quest.sections = [429] = function(player, csid, option, npc) if quest:getVar(player, 'Prog') == 0 then quest:setVar(player, 'Prog', 1) - quest:setVar(player, 'HourStarted', VanadielHour()) -- Set current quest started variables. - quest:setVar(player, 'DayStarted', VanadielDayOfTheYear()) -- Set current quest started variables. + quest:setVar(player, 'EndTime', VanadielTime() + xi.vanaTime.DAY) -- Set current quest started variables. end end, @@ -165,9 +164,10 @@ quest.sections = ['_6n2'] = { onTrigger = function(player, npc) - local daysPassed = VanadielDayOfTheYear() - quest:getVar(player, 'DayStarted') - local totalHoursLeft = 24 - (VanadielHour() + daysPassed * 24) + quest:getVar(player, 'HourStarted') - if totalHoursLeft > 0 then + local currentTime = VanadielTime() + local endTime = quest:getVar(player, 'EndTime') + + if currentTime < endTime then return quest:progressEvent(289) end end, diff --git a/scripts/specs/core/CBaseEntity.lua b/scripts/specs/core/CBaseEntity.lua index bf944a51c93..55d418b366e 100644 --- a/scripts/specs/core/CBaseEntity.lua +++ b/scripts/specs/core/CBaseEntity.lua @@ -1042,12 +1042,12 @@ end ---@nodiscard ---@param name string ----@param mobFamily integer +---@param interestData integer ---@param zeni integer ---@param skillIndex integer ---@param fp integer ---@return CItem? -function CBaseEntity:addSoulPlate(name, mobFamily, zeni, skillIndex, fp) +function CBaseEntity:addSoulPlate(name, interestData, zeni, skillIndex, fp) end ---@nodiscard diff --git a/scripts/specs/core/CItem.lua b/scripts/specs/core/CItem.lua index 273151b65ff..3914ce15a8c 100644 --- a/scripts/specs/core/CItem.lua +++ b/scripts/specs/core/CItem.lua @@ -181,12 +181,12 @@ function CItem:isInstalled() end ---@param name string ----@param mobFamily integer +---@param interestData integer ---@param zeni integer ---@param skillIndex integer ---@param fp integer ---@return nil -function CItem:setSoulPlateData(name, mobFamily, zeni, skillIndex, fp) +function CItem:setSoulPlateData(name, interestData, zeni, skillIndex, fp) end ---@nodiscard diff --git a/scripts/zones/Caedarva_Mire/npcs/qm8.lua b/scripts/zones/Caedarva_Mire/npcs/qm8.lua index 41e44437cb0..3aa993c9d72 100644 --- a/scripts/zones/Caedarva_Mire/npcs/qm8.lua +++ b/scripts/zones/Caedarva_Mire/npcs/qm8.lua @@ -9,9 +9,9 @@ local ID = zones[xi.zone.CAEDARVA_MIRE] local entity = {} entity.onTrigger = function(player, npc) - if player:getCharVar('[TIMER]Lamian_Fang_Key') ~= VanadielDayOfTheYear() then + if player:getCharVar('[TIMER]Lamian_Fang_Key') ~= VanadielUniqueDay() then if npcUtil.giveItem(player, xi.item.LAMIAN_FANG_KEY) then - player:setCharVar('[TIMER]Lamian_Fang_Key', VanadielDayOfTheYear()) -- Can obtain key once per vanadiel day + player:setCharVar('[TIMER]Lamian_Fang_Key', VanadielUniqueDay()) -- Can obtain key once per vanadiel day end else player:messageSpecial(ID.text.NOTHING_OUT_OF_ORDINARY) diff --git a/scripts/zones/Castle_Zvahl_Baileys/npcs/Switchstix.lua b/scripts/zones/Castle_Zvahl_Baileys/npcs/Switchstix.lua index 9936efd2638..75a42e4f112 100644 --- a/scripts/zones/Castle_Zvahl_Baileys/npcs/Switchstix.lua +++ b/scripts/zones/Castle_Zvahl_Baileys/npcs/Switchstix.lua @@ -17,113 +17,759 @@ local currencyAmount = 3 local stageNumber = 4 local csParam = 5 -local currency = -{ - BYNE_100 = 1456, - BYNE_10000 = 1457, - SILVER_100 = 1453, - SILVER_10000 = 1454, - SHELL_100 = 1450, - SHELL_10000 = 1451, -} - local relics = { -- Spharai - [18260] = { { 1460, 1459, 665 }, currency.BYNE_100, 4, 1, 1 }, -- Relic Knuckles - [18261] = { { 16390, 16392, 16396 }, currency.SILVER_100, 14, 2, 2 }, -- Militant Knuckles - [18262] = { { 1556 }, currency.SHELL_100, 61, 3, 3 }, -- Dynamis Knuckles - [18263] = { { 1571, 1589 }, currency.BYNE_10000, 1, 4, 3 }, -- Caestus + [xi.item.RELIC_KNUCKLES] = + { + { + xi.item.KOH_I_NOOR, + xi.item.SQUARE_OF_GRIFFON_LEATHER, + xi.item.ADAMAN_SHEET + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 4, + 1, + 1 + }, + [xi.item.MILITANT_KNUCKLES] = + { + { + xi.item.BRONZE_KNUCKLES, + xi.item.METAL_KNUCKLES, + xi.item.KOENIGS_KNUCKLES + }, + xi.item.MONTIONT_SILVERPIECE, + 14, + 2, + 2 + }, + [xi.item.DYNAMIS_KNUCKLES] = + { + { + xi.item.ATTESTATION_OF_MIGHT + }, + xi.item.LUNGO_NANGO_JADESHELL, + 61, + 3, + 3 + }, + [xi.item.CAESTUS] = + { + { + xi.item.MYSTIC_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.TEN_THOUSAND_BYNE_BILL, + 1, + 4, + 3 + }, -- Mandau - [18266] = { { 4246, 747, 4166 }, currency.BYNE_100, 4, 1, 1 }, -- Relic Dagger - [18267] = { { 16449, 16496, 16452 }, currency.SILVER_100, 14, 2, 2 }, -- Malefic Dagger - [18268] = { { 1557 }, currency.SHELL_100, 61, 3, 3 }, -- Dynamis Dagger - [18269] = { { 1572, 1589 }, currency.BYNE_10000, 1, 4, 3 }, -- Batardeau + [xi.item.RELIC_DAGGER] = + { + { + xi.item.BOTTLE_OF_CANTARELLA, + xi.item.ORICHALCUM_INGOT, + xi.item.FLASK_OF_DEODORIZER + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 4, + 1, + 1 + }, + [xi.item.MALEFIC_DAGGER] = + { + { + xi.item.BRASS_DAGGER, + xi.item.POISON_DAGGER, + xi.item.MISERICORDE + }, + xi.item.MONTIONT_SILVERPIECE, + 14, + 2, + 2 + }, + [xi.item.DYNAMIS_DAGGER] = + { + { + xi.item.ATTESTATION_OF_CELERITY + }, + xi.item.LUNGO_NANGO_JADESHELL, + 61, + 3, + 3 + }, + [xi.item.BATARDEAU] = + { + { + xi.item.ORNATE_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.TEN_THOUSAND_BYNE_BILL, + 1, + 4, + 3 + }, -- Excalibur - [18272] = { { 1460, 763, 931 }, currency.SILVER_100, 4, 1, 1 }, -- Relic Sword - [18273] = { { 16535, 16537, 16542 }, currency.BYNE_100, 14, 2, 2 }, -- Glyptic Sword - [18274] = { { 1558 }, currency.SHELL_100, 61, 3, 3 }, -- Dynamis Sword - [18275] = { { 1573, 1589 }, currency.SILVER_10000, 1, 4, 3 }, -- Caliburn + [xi.item.RELIC_SWORD] = + { + { + xi.item.KOH_I_NOOR, + xi.item.ORICHALCUM_CHAIN, + xi.item.CERMET_CHUNK + }, + xi.item.MONTIONT_SILVERPIECE, + 4, + 1, + 1 + }, + [xi.item.GLYPTIC_SWORD] = + { + { + xi.item.BRONZE_SWORD, + xi.item.MYTHRIL_SWORD, + xi.item.WING_SWORD + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 14, + 2, + 2 + }, + [xi.item.DYNAMIS_SWORD] = + { + { + xi.item.ATTESTATION_OF_GLORY + }, + xi.item.LUNGO_NANGO_JADESHELL, + 61, + 3, + 3 + }, + [xi.item.CALIBURN] = + { + { + xi.item.HOLY_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 3 + }, -- Ragnarok - [18278] = { { 1459, 655, 746 }, currency.SILVER_100, 4, 1, 1 }, -- Relic Blade - [18279] = { { 16583, 16584, 16585 }, currency.SHELL_100, 14, 2, 2 }, -- Gilded Blade - [18280] = { { 1559 }, currency.BYNE_100, 61, 3, 3 }, -- Dynamis Blade - [18281] = { { 1574, 1589 }, currency.SILVER_10000, 1, 4, 3 }, -- Valhalla + [xi.item.RELIC_BLADE] = + { + { + xi.item.SQUARE_OF_GRIFFON_LEATHER, + xi.item.ADAMAN_INGOT, + xi.item.PLATINUM_INGOT + }, + xi.item.MONTIONT_SILVERPIECE, + 4, + 1, + 1 + }, + [xi.item.GILDED_BLADE] = + { + { + xi.item.CLAYMORE, + xi.item.MYTHRIL_CLAYMORE, + xi.item.DARKSTEEL_CLAYMORE + }, + xi.item.LUNGO_NANGO_JADESHELL, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_BLADE] = + { + { + xi.item.ATTESTATION_OF_RIGHTEOUSNESS + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 61, + 3, + 3 + }, + [xi.item.VALHALLA] = + { + { + xi.item.INTRICATE_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 3 + }, -- Guttler - [18284] = { { 1312, 1463, 13060 }, currency.SHELL_100, 3, 1, 1 }, -- Relic Axe - [18285] = { { 16657, 16658, 16659 }, currency.SILVER_100, 14, 2, 2 }, -- Leonine Axe - [18286] = { { 1560 }, currency.BYNE_100, 60, 3, 3 }, -- Dynamis Axe - [18287] = { { 1575, 1589 }, currency.SHELL_10000, 1, 4, 3 }, -- Ogre Killer + [xi.item.RELIC_AXE] = + { + { + xi.item.PIECE_OF_ANGEL_SKIN, + xi.item.CHRONOS_TOOTH, + xi.item.FEATHER_COLLAR_P1 + }, + xi.item.LUNGO_NANGO_JADESHELL, + 3, + 1, + 1 + }, + [xi.item.LEONINE_AXE] = + { + { + xi.item.TABAR, + xi.item.DARKSTEEL_TABAR, + xi.item.TABARZIN + }, + xi.item.MONTIONT_SILVERPIECE, + 14, + 2, + 2 + }, + [xi.item.DYNAMIS_AXE] = + { + { + xi.item.ATTESTATION_OF_BRAVERY + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 60, + 3, + 3 + }, + [xi.item.OGRE_KILLER] = + { + { + xi.item.RUNAEIC_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RIMILALA_STRIPESHELL, + 1, + 4, + 3 + }, -- Bravura - [18290] = { { 1461, 658, 720 }, currency.BYNE_100, 3, 1, 1 }, -- Relic Bhuj - [18291] = { { 16704, 16705, 16724 }, currency.SHELL_100, 16, 2, 2 }, -- Agonal Bhuj - [18292] = { { 1561 }, currency.SILVER_100, 60, 3, 3 }, -- Dynamis Bhuj - [18293] = { { 1576, 1589 }, currency.BYNE_10000, 1, 4, 3 }, -- Abaddon Killer + [xi.item.RELIC_BHUJ] = + { + { + xi.item.WOOTZ_INGOT, + xi.item.DAMASCUS_INGOT, + xi.item.PIECE_OF_ANCIENT_LUMBER + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 3, + 1, + 1 + }, + [xi.item.AGONAL_BHUJ] = + { + { + xi.item.BUTTERFLY_AXE, + xi.item.GREATAXE, + xi.item.HEAVY_DARKSTEEL_AXE + }, + xi.item.LUNGO_NANGO_JADESHELL, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_BHUJ] = + { + { + xi.item.ATTESTATION_OF_FORCE + }, + xi.item.MONTIONT_SILVERPIECE, + 60, + 3, + 3 + }, + [xi.item.ABADDON_KILLER] = + { + { + xi.item.SERAPHIC_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.TEN_THOUSAND_BYNE_BILL, + 1, + 4, + 3 + }, -- Gungnir - [18296] = { { 1462, 747, 1294 }, currency.SHELL_100, 4, 1, 1 }, -- Relic Lance - [18297] = { { 16834, 16836, 16841 }, currency.BYNE_100, 16, 2, 2 }, -- Hotspur Lance - [18298] = { { 1563 }, currency.SILVER_100, 61, 3, 3 }, -- Dynamis Lance - [18299] = { { 1578, 1589 }, currency.SHELL_10000, 1, 4, 3 }, -- Gae Assail + [xi.item.RELIC_LANCE] = + { + { + xi.item.PIECE_OF_LANCEWOOD_LUMBER, + xi.item.ORICHALCUM_INGOT, + xi.item.SPOOL_OF_ARACHNE_THREAD + }, + xi.item.LUNGO_NANGO_JADESHELL, + 4, + 1, + 1 + }, + [xi.item.HOTSPUR_LANCE] = + { + { + xi.item.BRASS_SPEAR, + xi.item.HALBERD, + xi.item.WYVERN_SPEAR + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_LANCE] = + { + { + xi.item.ATTESTATION_OF_FORTITUDE + }, + xi.item.MONTIONT_SILVERPIECE, + 61, + 3, + 3 + }, + [xi.item.GAE_ASSAIL] = + { + { + xi.item.STELLAR_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RIMILALA_STRIPESHELL, + 1, + 4, + 3 + }, -- Apocalypse - [18302] = { { 1458, 1117, 13208 }, currency.SHELL_100, 5, 1, 1 }, -- Relic Scythe - [18303] = { { 16774, 16794, 16777 }, currency.SILVER_100, 16, 2, 2 }, -- Memento Scythe - [18304] = { { 1562 }, currency.BYNE_100, 62, 3, 3 }, -- Dynamis Scythe - [18305] = { { 1577, 1589 }, currency.SHELL_10000, 1, 4, 3 }, -- Bec De Faucon + [xi.item.RELIC_SCYTHE] = + { + { + xi.item.MAMMOTH_TUSK, + xi.item.SQUARE_OF_MANTICORE_LEATHER, + xi.item.RAINBOW_OBI + }, + xi.item.LUNGO_NANGO_JADESHELL, + 5, + 1, + 1 + }, + [xi.item.MEMENTO_SCYTHE] = + { + { + xi.item.SCYTHE, + xi.item.BONE_SCYTHE, + xi.item.DEATH_SCYTHE + }, + xi.item.MONTIONT_SILVERPIECE, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_SCYTHE] = + { + { + xi.item.ATTESTATION_OF_VIGOR + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 62, + 3, + 3 + }, + [xi.item.BEC_DE_FAUCON] = + { + { + xi.item.TENEBROUS_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RIMILALA_STRIPESHELL, + 1, + 4, + 3 + }, -- Kikoku - [18308] = { { 1467, 1276, 1278 }, currency.BYNE_100, 4, 1, 1 }, -- Ihintanto - [18309] = { { 16900, 16903, 16902 }, currency.SHELL_100, 16, 2, 2 }, -- Mimizuku - [18310] = { { 1564 }, currency.SILVER_100, 61, 3, 3 }, -- Rogetsu - [18311] = { { 1579, 1589 }, currency.BYNE_10000, 1, 4, 3 }, -- Yoshimitsu + [xi.item.IHINTANTO] = + { + { + xi.item.CHUNK_OF_RELIC_STEEL, + xi.item.TARASQUE_SKIN, + xi.item.SPOOL_OF_TWINTHREAD + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 4, + 1, + 1 + }, + [xi.item.MIMIZUKU] = + { + { + xi.item.WAKIZASHI, + xi.item.KABUTOWARI, + xi.item.SAKURAFUBUKI + }, + xi.item.LUNGO_NANGO_JADESHELL, + 16, + 2, + 2 + }, + [xi.item.ROGETSU] = + { + { + xi.item.ATTESTATION_OF_LEGERITY + }, + xi.item.MONTIONT_SILVERPIECE, + 61, + 3, + 3 + }, + [xi.item.YOSHIMITSU] = + { + { + xi.item.DEMONIAC_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.TEN_THOUSAND_BYNE_BILL, + 1, + 4, + 3 + }, -- Amanomurakumo - [18314] = { { 1467, 1409, 657 }, currency.SILVER_100, 3, 1, 1 }, -- Ito - [18315] = { { 16966, 16967, 16972 }, currency.SHELL_100, 15, 2, 2 }, -- Hayatemaru - [18316] = { { 1565 }, currency.BYNE_100, 60, 3, 3 }, -- Oboromaru - [18317] = { { 1580, 1589 }, currency.SILVER_10000, 1, 4, 3 }, -- Totsukanotsurugi + [xi.item.ITO] = + { + { + xi.item.CHUNK_OF_RELIC_STEEL, + xi.item.SPOOL_OF_SIRENS_MACRAME, + xi.item.LUMP_OF_TAMA_HAGANE + }, + xi.item.MONTIONT_SILVERPIECE, + 3, + 1, + 1 + }, + [xi.item.HAYATEMARU] = + { + { + xi.item.TACHI, + xi.item.MIKAZUKI, + xi.item.KAZARIDACHI + }, + xi.item.LUNGO_NANGO_JADESHELL, + 15, + 2, + 2 + }, + [xi.item.OBOROMARU] = + { + { + xi.item.ATTESTATION_OF_DECISIVENESS + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 60, + 3, + 3 + }, + [xi.item.TOTSUKANOTSURUGI] = + { + { + xi.item.DIVINE_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 3 + }, -- Mjollnir - [18320] = { { 1461, 746, 830 }, currency.SILVER_100, 5, 1, 1 }, -- Relic Maul - [18321] = { { 17044, 17080, 17043 }, currency.BYNE_100, 16, 2, 2 }, -- Battering Maul - [18322] = { { 1566 }, currency.SHELL_100, 62, 3, 3 }, -- Dynamis Maul - [18323] = { { 1581, 1589 }, currency.SILVER_10000, 1, 4, 3 }, -- Gullintani + [xi.item.RELIC_MAUL] = + { + { + xi.item.WOOTZ_INGOT, + xi.item.PLATINUM_INGOT, + xi.item.SQUARE_OF_RAINBOW_CLOTH + }, + xi.item.MONTIONT_SILVERPIECE, + 5, + 1, + 1 + }, + [xi.item.BATTERING_MAUL] = + { + { + xi.item.WARHAMMER, + xi.item.HOLY_MAUL, + xi.item.BRASS_HAMMER + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_MAUL] = + { + { + xi.item.ATTESTATION_OF_SACRIFICE + }, + xi.item.LUNGO_NANGO_JADESHELL, + 62, + 3, + 3 + }, + [xi.item.GULLINTANI] = + { + { + xi.item.HEAVENLY_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 3 + }, -- Claustrum - [18326] = { { 1462, 1271, 1415 }, currency.SHELL_100, 5, 1, 1 }, -- Relic Staff - [18327] = { { 17088, 17090, 17092 }, currency.BYNE_100, 16, 2, 2 }, -- Sage's Staff - [18328] = { { 1567 }, currency.SILVER_100, 62, 3, 3 }, -- Dynamis Staff - [18329] = { { 1582, 1589 }, currency.SHELL_10000, 1, 4, 3 }, -- Thyrus + [xi.item.RELIC_STAFF] = + { + { + xi.item.PIECE_OF_LANCEWOOD_LUMBER, + xi.item.PIGEONS_BLOOD_RUBY, + xi.item.POT_OF_URUSHI + }, + xi.item.LUNGO_NANGO_JADESHELL, + 5, + 1, + 1 + }, + [xi.item.SAGES_STAFF] = + { + { + xi.item.ASH_STAFF, + xi.item.ELM_STAFF, + xi.item.MAHOGANY_STAFF + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 16, + 2, + 2 + }, + [xi.item.DYNAMIS_STAFF] = + { + { + xi.item.ATTESTATION_OF_VIRTUE + }, + xi.item.MONTIONT_SILVERPIECE, + 62, + 3, + 3 + }, + [xi.item.THYRUS] = + { + { + xi.item.CELESTIAL_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RIMILALA_STRIPESHELL, + 1, + 4, + 3 + }, -- Annihilator - [18332] = { { 1468, 830, 654 }, currency.BYNE_100, 5, 1, 1 }, -- Relic Gun - [18333] = { { 17248, 17251, 17259 }, currency.SHELL_100, 15, 2, 2 }, -- Marksman Gun - [18334] = { { 1570 }, currency.SILVER_100, 62, 3, 3 }, -- Dynamis Gun - [18335] = { { 1585, 1589 }, currency.BYNE_10000, 1, 4, 3 }, -- Ferdinand + [xi.item.RELIC_GUN] = + { + { + xi.item.FLASK_OF_MARKSMANS_OIL, + xi.item.SQUARE_OF_RAINBOW_CLOTH, + xi.item.DARKSTEEL_INGOT + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 5, + 1, + 1 + }, + [xi.item.MARKSMANS_GUN] = + { + { + xi.item.ARQUEBUS, + xi.item.HELLFIRE, + xi.item.PIRATES_GUN + }, + xi.item.LUNGO_NANGO_JADESHELL, + 15, + 2, + 2 + }, + [xi.item.DYNAMIS_GUN] = + { + { + xi.item.ATTESTATION_OF_ACCURACY + }, + xi.item.MONTIONT_SILVERPIECE, + 62, + 3, + 3 + }, + [xi.item.FERDINAND] = + { + { + xi.item.ETHEREAL_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.TEN_THOUSAND_BYNE_BILL, + 1, + 4, + 3 + }, -- Gjallarhorn - [18338] = { { 1458, 1463, 13232 }, currency.SHELL_100, 3, 1, 1 }, -- Relic Horn - [18339] = { { 17352, 17351, 17362 }, currency.BYNE_100, 14, 2, 2 }, -- Pyrrhic Horn - [18340] = { { 1569 }, currency.SILVER_100, 60, 3, 3 }, -- Dynamis Horn - [18341] = { { 1584, 1589 }, currency.SHELL_10000, 1, 4, 3 }, -- Milennium Horn + [xi.item.RELIC_HORN] = + { + { + xi.item.MAMMOTH_TUSK, + xi.item.CHRONOS_TOOTH, + xi.item.SWORDBELT_P1 + }, + xi.item.LUNGO_NANGO_JADESHELL, + 3, + 1, + 1 + }, + [xi.item.PYRRHIC_HORN] = + { + { + xi.item.HORN, + xi.item.GEMSHORN, + xi.item.SHOFAR + }, + xi.item.ONE_HUNDRED_BYNE_BILL, + 14, + 2, + 2 + }, + [xi.item.DYNAMIS_HORN] = + { + { + xi.item.ATTESTATION_OF_HARMONY + }, + xi.item.MONTIONT_SILVERPIECE, + 60, + 3, + 3 + }, + [xi.item.MILLENNIUM_HORN] = + { + { + xi.item.MYSTERIAL_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RIMILALA_STRIPESHELL, + 1, + 4, + 3 + }, -- Yoichinoyumi - [18344] = { { 883, 1462, 932 }, currency.SILVER_100, 4, 1, 1 }, -- Relic Bow - [18345] = { { 17161, 17164, 18142 }, currency.SILVER_100, 15, 2, 2 }, -- Wolver Bow - [18346] = { { 1568 }, currency.SHELL_100, 61, 3, 3 }, -- Dynamis Bow - [18347] = { { 1583, 1589 }, currency.SILVER_10000, 1, 4, 3 }, -- Futatokoroto + [xi.item.RELIC_BOW] = + { + { + xi.item.BEHEMOTH_HORN, + xi.item.PIECE_OF_LANCEWOOD_LUMBER, + xi.item.LOOP_OF_CARBON_FIBER + }, + xi.item.MONTIONT_SILVERPIECE, + 4, + 1, + 1 + }, + [xi.item.WOLVER_BOW] = + { + { + xi.item.POWER_BOW, + xi.item.WAR_BOW, + xi.item.SHIGETO_BOW + }, + xi.item.MONTIONT_SILVERPIECE, + 15, + 2, + 2 + }, + [xi.item.DYNAMIS_BOW] = + { + { + xi.item.ATTESTATION_OF_TRANSCENDENCE + }, + xi.item.LUNGO_NANGO_JADESHELL, + 61, + 3, + 3 + }, + [xi.item.FUTATOKOROTO] = + { + { + xi.item.SNARLED_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 3 + }, -- Aegis - [15066] = { { 875, 668, 720 }, 0, 1, 1, 4 }, -- Relic Shield - [15067] = { { 12301, 12295, 12387 }, 0, 4, 2, 5 }, -- Bulwark Shield - [15068] = { { 1821 }, 0, 20, 3, 6 }, -- Dynamis Shield - [15069] = { { 1822, 1589 }, currency.SILVER_10000, 1, 4, 6 }, -- Ancile + [xi.item.RELIC_SHIELD] = + { + { + xi.item.SQUARE_OF_AMALTHEIA_LEATHER, + xi.item.ORICHALCUM_SHEET, + xi.item.PIECE_OF_ANCIENT_LUMBER + }, + 0, + 1, + 1, + 4 + }, + [xi.item.BULWARK_SHIELD] = + { + { + xi.item.BUCKLER, + xi.item.ROUND_SHIELD, + xi.item.KOENIG_SHIELD + }, + 0, + 4, + 2, + 5 + }, + [xi.item.DYNAMIS_SHIELD] = + { + { + xi.item.ATTESTATION_OF_INVULNERABILITY + }, + 0, + 20, + 3, + 6 + }, + [xi.item.ANCILE] = + { + { + xi.item.SUPERNAL_FRAGMENT, + xi.item.SHARD_OF_NECROPSYCHE + }, + xi.item.RANPERRE_GOLDPIECE, + 1, + 4, + 6 + } } local function hasRelic(player, isTrade) @@ -149,13 +795,24 @@ end local function tradeHasRequiredCurrency(trade, currentRelic) local relic = relics[currentRelic] - if currentRelic == 15066 or currentRelic == 15067 or currentRelic == 15068 then - if currentRelic == 15066 and trade:getItemCount() == 3 then - return trade:hasItemQty(currency.BYNE_100, 1) and trade:hasItemQty(currency.SILVER_100, 1) and trade:hasItemQty(currency.SHELL_100, 1) - elseif currentRelic == 15067 and trade:getItemCount() == 12 then - return trade:hasItemQty(currency.BYNE_100, 4) and trade:hasItemQty(currency.SILVER_100, 4) and trade:hasItemQty(currency.SHELL_100, 4) - elseif currentRelic == 15068 and trade:getItemCount() == 60 then - return trade:hasItemQty(currency.BYNE_100, 20) and trade:hasItemQty(currency.SILVER_100, 20) and trade:hasItemQty(currency.SHELL_100, 20) + -- Aegis multi-currency trades + if + currentRelic == xi.item.RELIC_SHIELD or + currentRelic == xi.item.BULWARK_SHIELD or + currentRelic == xi.item.DYNAMIS_SHIELD + then + if currentRelic == xi.item.RELIC_SHIELD and trade:getItemCount() == 3 then + return trade:hasItemQty(xi.item.ONE_HUNDRED_BYNE_BILL, 1) and + trade:hasItemQty(xi.item.MONTIONT_SILVERPIECE, 1) and + trade:hasItemQty(xi.item.LUNGO_NANGO_JADESHELL, 1) + elseif currentRelic == xi.item.BULWARK_SHIELD and trade:getItemCount() == 12 then + return trade:hasItemQty(xi.item.ONE_HUNDRED_BYNE_BILL, 4) and + trade:hasItemQty(xi.item.MONTIONT_SILVERPIECE, 4) and + trade:hasItemQty(xi.item.LUNGO_NANGO_JADESHELL, 4) + elseif currentRelic == xi.item.DYNAMIS_SHIELD and trade:getItemCount() == 60 then + return trade:hasItemQty(xi.item.ONE_HUNDRED_BYNE_BILL, 20) and + trade:hasItemQty(xi.item.MONTIONT_SILVERPIECE, 20) and + trade:hasItemQty(xi.item.LUNGO_NANGO_JADESHELL, 20) else return false end @@ -292,25 +949,24 @@ entity.onTrigger = function(player, npc) elseif currentStage == 3 then player:startEvent(50, relicId, requiredItem1, requiredItem2, requiredItem3, 0, 0, 0, relic[csParam]) elseif currentStage == 4 then - -- TODO: Use xi.items enum in key for the below table local itemToEventId = { - [18263] = 68, -- Spharai - [18269] = 69, -- Mandau - [18275] = 70, -- Excalibur - [18281] = 71, -- Ragnarok - [18287] = 72, -- Guttler - [18293] = 73, -- Bravura - [18299] = 75, -- Gungnir - [18305] = 74, -- Apocalypse - [18311] = 76, -- Kikoku - [18317] = 77, -- Amanomurakumo - [18323] = 78, -- Mjollnir - [18329] = 79, -- Claustrum - [18335] = 81, -- Annihilator - [18341] = 82, -- Gjallarhorn - [18347] = 80, -- Yoichinoyumi - [15069] = 86, -- Aegis + [xi.item.CAESTUS] = 68, -- Spharai + [xi.item.BATARDEAU] = 69, -- Mandau + [xi.item.CALIBURN] = 70, -- Excalibur + [xi.item.VALHALLA] = 71, -- Ragnarok + [xi.item.OGRE_KILLER] = 72, -- Guttler + [xi.item.ABADDON_KILLER] = 73, -- Bravura + [xi.item.GAE_ASSAIL] = 75, -- Gungnir + [xi.item.BEC_DE_FAUCON] = 74, -- Apocalypse + [xi.item.YOSHIMITSU] = 76, -- Kikoku + [xi.item.TOTSUKANOTSURUGI] = 77, -- Amanomurakumo + [xi.item.GULLINTANI] = 78, -- Mjollnir + [xi.item.THYRUS] = 79, -- Claustrum + [xi.item.FERDINAND] = 81, -- Annihilator + [xi.item.MILLENNIUM_HORN] = 82, -- Gjallarhorn + [xi.item.FUTATOKOROTO] = 80, -- Yoichinoyumi + [xi.item.ANCILE] = 86, -- Aegis } player:startEvent(itemToEventId[relicId], requiredItem1, requiredItem2, relic[currencyType], relic[currencyAmount], relicId) @@ -324,11 +980,20 @@ entity.onEventUpdate = function(player, csid, option, npc) -- Handles the displayed currency types and amounts for Aegis Stage 1->2, 2->3, and 3->4 based on option. if (csid == 11 or csid == 12 or csid == 13) and option ~= 0 then if option == 1 then - player:updateEvent(15066, 1453, 1, 1456, 1, 1450, 1) + player:updateEvent(xi.item.RELIC_SHIELD, + xi.item.MONTIONT_SILVERPIECE, 1, + xi.item.ONE_HUNDRED_BYNE_BILL, 1, + xi.item.LUNGO_NANGO_JADESHELL, 1) elseif option == 2 then - player:updateEvent(15067, 1453, 4, 1456, 4, 1450, 4) + player:updateEvent(xi.item.BULWARK_SHIELD, + xi.item.MONTIONT_SILVERPIECE, 4, + xi.item.ONE_HUNDRED_BYNE_BILL, 4, + xi.item.LUNGO_NANGO_JADESHELL, 4) elseif option == 3 then - player:updateEvent(15068, 1453, 20, 1456, 20, 1450, 20) + player:updateEvent(xi.item.DYNAMIS_SHIELD, + xi.item.MONTIONT_SILVERPIECE, 20, + xi.item.ONE_HUNDRED_BYNE_BILL, 20, + xi.item.LUNGO_NANGO_JADESHELL, 20) end end end @@ -375,25 +1040,24 @@ entity.onEventFinish = function(player, csid, option, npc) -- Stage 4 cutscenes elseif (csid >= 68 and csid <= 82) or csid == 86 then - -- TODO: Use xi.items enum below local eventToItemId = { - [68] = 18263, -- Spharai - [69] = 18269, -- Mandau - [70] = 18275, -- Excalibur - [71] = 18281, -- Ragnarok - [72] = 18287, -- Guttler - [73] = 18293, -- Bravura - [75] = 18299, -- Gungnir - [74] = 18305, -- Apocalypse - [76] = 18311, -- Kikoku - [77] = 18317, -- Amanomurakumo - [78] = 18323, -- Mjollnir - [79] = 18329, -- Claustrum - [81] = 18335, -- Annihilator - [82] = 18341, -- Gjallarhorn - [80] = 18347, -- Yoichinoyumi - [86] = 15069, -- Aegis + [68] = xi.item.CAESTUS, -- Spharai + [69] = xi.item.BATARDEAU, -- Mandau + [70] = xi.item.CALIBURN, -- Excalibur + [71] = xi.item.VALHALLA, -- Ragnarok + [72] = xi.item.OGRE_KILLER, -- Guttler + [73] = xi.item.ABADDON_KILLER, -- Bravura + [75] = xi.item.GAE_ASSAIL, -- Gungnir + [74] = xi.item.BEC_DE_FAUCON, -- Apocalypse + [76] = xi.item.YOSHIMITSU, -- Kikoku + [77] = xi.item.TOTSUKANOTSURUGI, -- Amanomurakumo + [78] = xi.item.GULLINTANI, -- Mjollnir + [79] = xi.item.THYRUS, -- Claustrum + [81] = xi.item.FERDINAND, -- Annihilator + [82] = xi.item.MILLENNIUM_HORN, -- Gjallarhorn + [80] = xi.item.FUTATOKOROTO, -- Yoichinoyumi + [86] = xi.item.ANCILE, -- Aegis } player:setCharVar('RELIC_CONQUEST_WAIT', 0) diff --git a/scripts/zones/Crawlers_Nest/npcs/qm9.lua b/scripts/zones/Crawlers_Nest/npcs/qm9.lua index 79648c68a65..a57fb3673df 100644 --- a/scripts/zones/Crawlers_Nest/npcs/qm9.lua +++ b/scripts/zones/Crawlers_Nest/npcs/qm9.lua @@ -12,7 +12,7 @@ local entity = {} entity.onTrigger = function(player, npc) if player:getQuestStatus(xi.questLog.SANDORIA, xi.quest.id.sandoria.A_BOYS_DREAM) == xi.questStatus.QUEST_ACCEPTED and - VanadielDayOfTheYear() ~= player:getCharVar('DreadbugNM_Day') + VanadielUniqueDay() ~= player:getCharVar('DreadbugNM_Day') then if os.time() > player:getCharVar('DreadbugNM_Timer') + 30 and @@ -20,7 +20,7 @@ entity.onTrigger = function(player, npc) then player:messageSpecial(ID.text.SENSE_OF_FOREBODING) player:setCharVar('DreadbugNM_Timer', os.time() + 180) - player:setCharVar('DreadbugNM_Day', VanadielDayOfTheYear()) + player:setCharVar('DreadbugNM_Day', VanadielUniqueDay()) else player:messageSpecial(ID.text.NOTHING_SEEMS_TO_HAPPEN) end diff --git a/scripts/zones/Lower_Jeuno/npcs/Chululu.lua b/scripts/zones/Lower_Jeuno/npcs/Chululu.lua index 8d693863fc3..2da8d3b61df 100644 --- a/scripts/zones/Lower_Jeuno/npcs/Chululu.lua +++ b/scripts/zones/Lower_Jeuno/npcs/Chululu.lua @@ -40,7 +40,7 @@ entity.onTrigger = function(player, npc) elseif collectTarutCards == xi.questStatus.QUEST_COMPLETED and rubbishDay == xi.questStatus.QUEST_AVAILABLE and - player:getCharVar('RubbishDay_day') ~= VanadielDayOfTheYear() + player:getCharVar('RubbishDay_day') ~= VanadielUniqueDay() then -- prog = player:getCharVar('RubbishDay_prog') -- if prog <= 2 then @@ -130,13 +130,13 @@ entity.onEventFinish = function(player, csid, option, npc) elseif csid == 199 and option == 0 then player:incrementCharVar('RubbishDay_prog', 1) - player:setCharVar('RubbishDay_day', VanadielDayOfTheYear()) -- new vanadiel day + player:setCharVar('RubbishDay_day', VanadielUniqueDay()) -- new vanadiel day elseif csid == 198 and option == 0 then player:addQuest(xi.questLog.JEUNO, xi.quest.id.jeuno.RUBBISH_DAY) npcUtil.giveKeyItem(player, xi.ki.MAGIC_TRASH) player:setCharVar('RubbishDay_prog', 0) - player:setCharVar('RubbishDay_day', VanadielDayOfTheYear()) + player:setCharVar('RubbishDay_day', VanadielUniqueDay()) elseif (csid == 10110 or csid == 10112 or csid == 10113) and diff --git a/scripts/zones/Lower_Jeuno/npcs/Kurou-Morou.lua b/scripts/zones/Lower_Jeuno/npcs/Kurou-Morou.lua index ea342270dfd..4356c5036c3 100644 --- a/scripts/zones/Lower_Jeuno/npcs/Kurou-Morou.lua +++ b/scripts/zones/Lower_Jeuno/npcs/Kurou-Morou.lua @@ -46,7 +46,7 @@ entity.onTrigger = function(player, npc) jeunoFame >= 5 and yourCrystalBall == xi.questStatus.QUEST_COMPLETED and player:getQuestStatus(xi.questLog.JEUNO, xi.quest.id.jeuno.NEVER_TO_RETURN) == xi.questStatus.QUEST_AVAILABLE and - player:getCharVar('QuestNeverToReturn_day') ~= VanadielDayOfTheYear() + player:getCharVar('QuestNeverToReturn_day') ~= VanadielUniqueDay() then local prog = player:getCharVar('QuestNeverToReturn_prog') if prog <= 2 then @@ -98,7 +98,7 @@ entity.onEventFinish = function(player, csid, option, npc) elseif csid == 204 and option == 0 then player:incrementCharVar('QuestNeverToReturn_prog', 1) -- Keep track of how many times the players fortune has been read - player:setCharVar('QuestNeverToReturn_day', VanadielDayOfTheYear()) -- new vanadiel day + player:setCharVar('QuestNeverToReturn_day', VanadielUniqueDay()) -- new vanadiel day elseif csid == 202 and option == 0 then player:addQuest(xi.questLog.JEUNO, xi.quest.id.jeuno.NEVER_TO_RETURN) diff --git a/scripts/zones/Mhaura/npcs/Nereus.lua b/scripts/zones/Mhaura/npcs/Nereus.lua index 114c6cfa63b..4cb83e0c418 100644 --- a/scripts/zones/Mhaura/npcs/Nereus.lua +++ b/scripts/zones/Mhaura/npcs/Nereus.lua @@ -27,10 +27,9 @@ entity.onTrigger = function(player, npc) player:startEvent(114, xi.item.DISH_OF_GUSGEN_CLAY) -- get me dish_of_gusgen_clay as soon as you can elseif player:getQuestStatus(xi.questLog.OTHER_AREAS, xi.quest.id.otherAreas.A_POTTERS_PREFERENCE) == xi.questStatus.QUEST_COMPLETED then if - player:getCharVar('QuestAPotterPrefeCompDay_var') + 7 < VanadielDayOfTheYear() or - player:getCharVar('QuestAPotterPrefeCompYear_var') < VanadielYear() + player:getCharVar('QuestAPotterPrefeCompDay_var') + 8 <= VanadielUniqueDay() then - -- seven days after copletition, allow to do the quest again + -- eight days after completion, allow to do the quest again player:startEvent(112) -- repeat quest else player:startEvent(115) -- i have enough for now, come later @@ -48,8 +47,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:addFame(xi.fameArea.WINDURST, 120) npcUtil.giveCurrency(player, 'gil', 2160) player:setCharVar('QuestAPotterPrefeRepeat_var', 0) - player:setCharVar('QuestAPotterPrefeCompDay_var', VanadielDayOfTheYear()) - player:setCharVar('QuestAPotterPrefeCompYear_var', VanadielYear()) + player:setCharVar('QuestAPotterPrefeCompDay_var', VanadielUniqueDay()) player:completeQuest(xi.questLog.OTHER_AREAS, xi.quest.id.otherAreas.A_POTTERS_PREFERENCE) elseif csid == 112 then --repeat quest player:setCharVar('QuestAPotterPrefeRepeat_var', 1) diff --git a/scripts/zones/Nashmau/npcs/Dnegan.lua b/scripts/zones/Nashmau/npcs/Dnegan.lua index 411806c4884..76b6b76ad8d 100644 --- a/scripts/zones/Nashmau/npcs/Dnegan.lua +++ b/scripts/zones/Nashmau/npcs/Dnegan.lua @@ -24,7 +24,7 @@ entity.onTrigger = function(player, npc) -- Quest: Operation Teatime elseif operationTeatimeProgress == 2 and - player:getCharVar('OTT_DayWait') ~= VanadielDayOfTheYear() + player:getCharVar('OTT_DayWait') ~= VanadielUniqueDay() then player:startEvent(290) -- CS for Chai else @@ -36,7 +36,7 @@ entity.onEventFinish = function(player, csid, option, npc) if csid == 289 then player:setCharVar('TheWaywardAutomatonProgress', 2) elseif csid == 290 and option == 0 then - player:setCharVar('OTT_DayWait', VanadielDayOfTheYear()) + player:setCharVar('OTT_DayWait', VanadielUniqueDay()) elseif csid == 290 and option == 1 then player:setCharVar('OperationTeatimeProgress', 3) player:setCharVar('OTT_DayWait', 0) diff --git a/scripts/zones/Rabao/npcs/Leodarion.lua b/scripts/zones/Rabao/npcs/Leodarion.lua index ecf0ca7ed93..d874387d50c 100644 --- a/scripts/zones/Rabao/npcs/Leodarion.lua +++ b/scripts/zones/Rabao/npcs/Leodarion.lua @@ -28,7 +28,7 @@ entity.onTrigger = function(player, npc) player:startEvent(91) elseif illTakeTheBigBoxCS == 3 and - VanadielDayOfTheYear() == player:getCharVar('illTakeTheBigBox_Timer') + VanadielUniqueDay() == player:getCharVar('illTakeTheBigBox_Timer') then player:startEvent(93) elseif illTakeTheBigBoxCS == 3 then @@ -56,7 +56,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:setCharVar('illTakeTheBigBoxCS', 2) elseif csid == 92 then player:tradeComplete() - player:setCharVar('illTakeTheBigBox_Timer', VanadielDayOfTheYear()) + player:setCharVar('illTakeTheBigBox_Timer', VanadielUniqueDay()) player:setCharVar('illTakeTheBigBoxCS', 3) elseif csid == 94 then player:setCharVar('illTakeTheBigBox_Timer', 0) diff --git a/scripts/zones/Windurst_Waters_[S]/npcs/Kocco_Ehllek.lua b/scripts/zones/Windurst_Waters_[S]/npcs/Kocco_Ehllek.lua index be5e7f4154a..6d617fb6039 100644 --- a/scripts/zones/Windurst_Waters_[S]/npcs/Kocco_Ehllek.lua +++ b/scripts/zones/Windurst_Waters_[S]/npcs/Kocco_Ehllek.lua @@ -19,7 +19,7 @@ entity.onTrigger = function(player, npc) player:startEvent(110) -- 4th CS quest "Redeeming Rocks" elseif redeemingRocks == xi.questStatus.QUEST_ACCEPTED and - player:getCharVar('RedeemingDay') ~= VanadielDayOfTheYear() + player:getCharVar('RedeemingDay') ~= VanadielUniqueDay() then player:startEvent(111) -- Last CS quest "Redeeming Rocks" else @@ -35,7 +35,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:setCharVar('RedeemingRocksProg', 3) elseif csid == 110 then -- Finish 'Redeeming Rocks' fourth CS player:setCharVar('RedeemingRocksProg', 0) - player:setCharVar('RedeemingDay', VanadielDayOfTheYear()) + player:setCharVar('RedeemingDay', VanadielUniqueDay()) elseif csid == 111 then -- Finish 'Redeeming Rocks' quest npcUtil.completeQuest(player, xi.questLog.CRYSTAL_WAR, xi.quest.id.crystalWar.REDEEMING_ROCKS, { item = 15998, diff --git a/scripts/zones/Yuhtunga_Jungle/npcs/Blue_Rafflesia.lua b/scripts/zones/Yuhtunga_Jungle/npcs/Blue_Rafflesia.lua index f23e1569f41..6029ab03496 100644 --- a/scripts/zones/Yuhtunga_Jungle/npcs/Blue_Rafflesia.lua +++ b/scripts/zones/Yuhtunga_Jungle/npcs/Blue_Rafflesia.lua @@ -13,8 +13,8 @@ entity.onTrigger = function(player, npc) local evenmoreTravelsStatus = player:getQuestStatus(xi.questLog.OUTLANDS, xi.quest.id.outlands.EVEN_MORE_GULLIBLES_TRAVELS) local questprogress = player:getCharVar('EVEN_MORE_GULLIBLES_PROGRESS') local scentDay = player:getCharVar('RafflesiaScentDay') - local currentDay = VanadielDayOfTheYear() - local scentReady = (scentDay < currentDay) or (scentDay > currentDay and player:getCharVar('RafflesiaScentYear') < VanadielYear()) + local currentDay = VanadielUniqueDay() + local scentReady = scentDay < currentDay local offset = npc:getID() - ID.npc.BLUE_RAFFLESIA_OFFSET if offset == 0 then @@ -86,8 +86,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:setCharVar('SecondBlueRafflesiaCS', 0) player:setCharVar('ThirdBlueRafflesiaCS', 0) player:setCharVar('BathedInScent', 1) - player:setCharVar('RafflesiaScentDay', VanadielDayOfTheYear()) - player:setCharVar('RafflesiaScentYear', VanadielYear()) + player:setCharVar('RafflesiaScentDay', VanadielUniqueDay()) npcUtil.giveItem(player, xi.item.JAR_OF_RAFFLESIA_NECTAR) player:messageSpecial(ID.text.FEEL_DIZZY) -- You feel slightly dizzy. You must have breathed in too much of the pollen. if evenmoreTravelsStatus == xi.questStatus.QUEST_ACCEPTED then @@ -105,8 +104,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:setCharVar('FirstBlueRafflesiaCS', 0) player:setCharVar('ThirdBlueRafflesiaCS', 0) player:setCharVar('BathedInScent', 1) - player:setCharVar('RafflesiaScentDay', VanadielDayOfTheYear()) - player:setCharVar('RafflesiaScentYear', VanadielYear()) + player:setCharVar('RafflesiaScentDay', VanadielUniqueDay()) npcUtil.giveItem(player, xi.item.JAR_OF_RAFFLESIA_NECTAR) player:messageSpecial(ID.text.FEEL_DIZZY) -- You feel slightly dizzy. You must have breathed in too much of the pollen. if evenmoreTravelsStatus == xi.questStatus.QUEST_ACCEPTED then @@ -124,8 +122,7 @@ entity.onEventFinish = function(player, csid, option, npc) player:setCharVar('FirstBlueRafflesiaCS', 0) player:setCharVar('SecondBlueRafflesiaCS', 0) player:setCharVar('BathedInScent', 1) - player:setCharVar('RafflesiaScentDay', VanadielDayOfTheYear()) - player:setCharVar('RafflesiaScentYear', VanadielYear()) + player:setCharVar('RafflesiaScentDay', VanadielUniqueDay()) npcUtil.giveItem(player, xi.item.JAR_OF_RAFFLESIA_NECTAR) player:messageSpecial(ID.text.FEEL_DIZZY) -- You feel slightly dizzy. You must have breathed in too much of the pollen. if evenmoreTravelsStatus == xi.questStatus.QUEST_ACCEPTED then diff --git a/sql/item_mods.sql b/sql/item_mods.sql index da1f09d28a4..b42d2632ded 100644 --- a/sql/item_mods.sql +++ b/sql/item_mods.sql @@ -4790,11 +4790,11 @@ INSERT INTO `item_mods` VALUES (11077,87,7); -- POLEARM: 7 INSERT INTO `item_mods` VALUES (11077,384,600); -- HASTE_GEAR: 600 -- Callers Horn +2 -INSERT INTO `item_mods` VALUES (11078,1,28); -- DEF: 28 -INSERT INTO `item_mods` VALUES (11078,5,30); -- MP: 30 -INSERT INTO `item_mods` VALUES (11078,117,9); -- SUMMONING: 9 -INSERT INTO `item_mods` VALUES (11078,369,2); -- REFRESH: 2 -INSERT INTO `item_mods` VALUES (11078,141,2); -- ENHANCES FAVOR: 2 +INSERT INTO `item_mods` VALUES (11078,1,28); -- DEF: 28 +INSERT INTO `item_mods` VALUES (11078,5,30); -- MP: 30 +INSERT INTO `item_mods` VALUES (11078,117,9); -- SUMMONING: 9 +INSERT INTO `item_mods` VALUES (11078,369,2); -- REFRESH: 2 +INSERT INTO `item_mods` VALUES (11078,1154,2); -- AVATARS_FAVOR_ENHANCE: 2 -- Mavi Kavuk +2 INSERT INTO `item_mods` VALUES (11079,1,34); -- DEF: 34 @@ -5503,11 +5503,11 @@ INSERT INTO `item_mods` VALUES (11177,23,14); -- ATT: 14 INSERT INTO `item_mods` VALUES (11177,384,500); -- HASTE_GEAR: 500 -- Callers Horn +1 -INSERT INTO `item_mods` VALUES (11178,1,26); -- DEF: 26 -INSERT INTO `item_mods` VALUES (11178,5,20); -- MP: 20 -INSERT INTO `item_mods` VALUES (11178,117,6); -- SUMMONING: 6 -INSERT INTO `item_mods` VALUES (11178,369,1); -- REFRESH: 1 -INSERT INTO `item_mods` VALUES (11178,141,1); -- ENHANCES FAVOR: 1 +INSERT INTO `item_mods` VALUES (11178,1,26); -- DEF: 26 +INSERT INTO `item_mods` VALUES (11178,5,20); -- MP: 20 +INSERT INTO `item_mods` VALUES (11178,117,6); -- SUMMONING: 6 +INSERT INTO `item_mods` VALUES (11178,369,1); -- REFRESH: 1 +INSERT INTO `item_mods` VALUES (11178,1154,1); -- AVATARS_FAVOR_ENHANCE: 1 -- Mavi Kavuk +1 INSERT INTO `item_mods` VALUES (11179,1,32); -- DEF: 32 @@ -48202,7 +48202,7 @@ INSERT INTO `item_mods` VALUES (23099,117,18); -- SUMMONING: 18 INSERT INTO `item_mods` VALUES (23099,160,-900); -- DMG: -900 INSERT INTO `item_mods` VALUES (23099,369,3); -- REFRESH: 3 INSERT INTO `item_mods` VALUES (23099,384,600); -- HASTE_GEAR: 6% -INSERT INTO `item_mods` VALUES (23099,141,4); -- AVATARS_FAVOR_ENHANCE: 4 +INSERT INTO `item_mods` VALUES (23099,1154,4); -- AVATARS_FAVOR_ENHANCE: 4 -- Hashishin Kavuk +2 INSERT INTO `item_mods` VALUES (23100,1,122); -- DEF: 122 @@ -64079,7 +64079,7 @@ INSERT INTO `item_mods` VALUES (26768,68,16); -- EVA: 16 INSERT INTO `item_mods` VALUES (26768,117,11); -- SUMMONING: 11 INSERT INTO `item_mods` VALUES (26768,369,2); -- REFRESH: 2 INSERT INTO `item_mods` VALUES (26768,384,500); -- HASTE_GEAR: 500 -INSERT INTO `item_mods` VALUES (26768,141,2); -- ENHANCES FAVOR: 2 +INSERT INTO `item_mods` VALUES (26768,1154,2); -- AVATARS_FAVOR_ENHANCE: 2 -- Beckoners Horn +1 INSERT INTO `item_mods` VALUES (26769,1,93); -- DEF: 93 @@ -64098,7 +64098,7 @@ INSERT INTO `item_mods` VALUES (26769,68,36); -- EVA: 36 INSERT INTO `item_mods` VALUES (26769,117,13); -- SUMMONING: 13 INSERT INTO `item_mods` VALUES (26769,369,2); -- REFRESH: 2 INSERT INTO `item_mods` VALUES (26769,384,600); -- HASTE_GEAR: 600 -INSERT INTO `item_mods` VALUES (26769,141,3); -- ENHANCES FAVOR: 3 +INSERT INTO `item_mods` VALUES (26769,1154,3); -- AVATARS_FAVOR_ENHANCE: 3 -- Hashishin Kavuk INSERT INTO `item_mods` VALUES (26770,1,71); -- DEF: 71 diff --git a/sql/item_mods_pet.sql b/sql/item_mods_pet.sql index 35dd40075c4..dceb085c506 100644 --- a/sql/item_mods_pet.sql +++ b/sql/item_mods_pet.sql @@ -82,6 +82,9 @@ INSERT INTO `item_mods_pet` VALUES (10972,164,-300,0); -- All Pets - DMGRANGE: - -- Esper Earring INSERT INTO `item_mods_pet` VALUES (11052,126,3,1); -- Avatar - BP_DAMAGE: 3 +-- Ferine Cabasset +2 +INSERT INTO `item_mods_pet` VALUES (11072,1155,20,0); -- All Pets - ENHANCES_MONSTER_CORRELATION: 20 + -- Callers Doublet +2 INSERT INTO `item_mods_pet` VALUES (11098,126,10,1); -- Avatar - BP_DAMAGE: 10 @@ -94,6 +97,9 @@ INSERT INTO `item_mods_pet` VALUES (11138,345,500,1); -- Avatar - TP_BONUS: 500 -- Callers Pigaches +2 INSERT INTO `item_mods_pet` VALUES (11158,30,5,1); -- Avatar - MACC: 5 +-- Ferine Cabasset +1 +INSERT INTO `item_mods_pet` VALUES (11172,1155,10,0); -- All Pets - ENHANCES_MONSTER_CORRELATION: 10 + -- Callers Doublet +1 INSERT INTO `item_mods_pet` VALUES (11198,126,5,1); -- Avatar - BP_DAMAGE: 5 @@ -750,7 +756,7 @@ INSERT INTO `item_mods_pet` VALUES (23083,2,500,8); -- Luopan - HP: 500 INSERT INTO `item_mods_pet` VALUES (23093,25,51,0); -- Pet: ACC: 51 INSERT INTO `item_mods_pet` VALUES (23093,26,51,0); -- Pet: RACC: 51 INSERT INTO `item_mods_pet` VALUES (23093,30,51,0); -- Pet: MACC: 51 --- TODO: Monster correlation effects +26 +INSERT INTO `item_mods_pet` VALUES (23093,1155,26,0); -- All Pets - ENHANCES_MONSTER_CORRELATION: 26 -- Peltast's Mezail +2 INSERT INTO `item_mods_pet` VALUES (23098,25,51,2); -- Wyvern - ACC: 51 @@ -1271,6 +1277,12 @@ INSERT INTO `item_mods_pet` VALUES (26677,2,110,1); -- Avatar - HP: 110 INSERT INTO `item_mods_pet` VALUES (26677,25,35,1); -- Avatar - ACC: 35 INSERT INTO `item_mods_pet` VALUES (26677,27,10,1); -- Avatar - ENMITY: 10 +-- Nukumi Cabasset +INSERT INTO `item_mods_pet` VALUES (26756,1155,22,0); -- All Pets - ENHANCES_MONSTER_CORRELATION: 22 + +-- Nukumi Cabasset +1 +INSERT INTO `item_mods_pet` VALUES (26757,1155,24,0); -- All Pets - ENHANCES_MONSTER_CORRELATION: 24 + -- Karagoz Capello INSERT INTO `item_mods_pet` VALUES (26774,345,525,3); -- Automaton - TP_BONUS: 525 diff --git a/sql/spell_list.sql b/sql/spell_list.sql index 6cf26cfc26c..256b339d99d 100644 --- a/sql/spell_list.sql +++ b/sql/spell_list.sql @@ -547,8 +547,8 @@ INSERT INTO `spell_list` VALUES (464,'goddesss_hymnus',0x00000000000000000047000 INSERT INTO `spell_list` VALUES (465,'chocobo_mazurka',0x00000000000000000049000000000000000000000000,1,139,@ELEMENT_WIND,8,129,@SKILL_SINGING,0,4000,60000,230,0,463,2000,5,0,1.00,11,44,0,204,NULL); INSERT INTO `spell_list` VALUES (466,'maidens_virelai',0x0000000000000000004B000000000000000000000000,1,0,@ELEMENT_LIGHT,0,4,@SKILL_SINGING,0,4000,60000,137,0,464,2000,0,0,1.00,11,44,0,164,NULL); INSERT INTO `spell_list` VALUES (467,'raptor_mazurka',0x00000000000000000025000000000000000000000000,1,139,@ELEMENT_WIND,8,129,@SKILL_SINGING,0,4000,24000,230,0,293,2000,5,0,1.00,11,44,0,204,'TOAU'); -INSERT INTO `spell_list` VALUES (468,'foe_sirvente',0x0000000000000000004B000000000000000000000000,1,0,@ELEMENT_LIGHT,0,3,@SKILL_SINGING,0,8000,24000,230,0,291,2000,0,0,1.00,11,44,0,204,'TOAU'); -INSERT INTO `spell_list` VALUES (469,'adventurers_dirge',0x0000000000000000004B000000000000000000000000,1,0,@ELEMENT_LIGHT,0,3,@SKILL_SINGING,0,8000,24000,230,0,292,2000,0,0,1.00,11,44,0,204,'TOAU'); +INSERT INTO `spell_list` VALUES (468,'foe_sirvente',0x0000000000000000004B000000000000000000000000,1,0,@ELEMENT_LIGHT,0,129,@SKILL_SINGING,0,8000,24000,230,0,291,2000,5,0,1.00,11,44,0,204,'TOAU'); +INSERT INTO `spell_list` VALUES (469,'adventurers_dirge',0x0000000000000000004B000000000000000000000000,1,0,@ELEMENT_LIGHT,0,129,@SKILL_SINGING,0,8000,24000,230,0,292,2000,5,0,1.00,11,44,0,204,'TOAU'); INSERT INTO `spell_list` VALUES (470,'sentinels_scherzo',0x00000000000000000052000000000000000000000000,1,0,@ELEMENT_EARTH,8,129,@SKILL_SINGING,0,8000,24000,230,0,465,2000,5,0,1.00,20,44,0,204,'ABYSSEA'); INSERT INTO `spell_list` VALUES (471,'foe_lullaby_ii',0x00000000000000000053000000000000000000000000,1,138,@ELEMENT_LIGHT,0,4,@SKILL_SINGING,0,2000,24000,237,0,376,2000,0,0,1.00,132,0,0,204,'ABYSSEA'); INSERT INTO `spell_list` VALUES (472,'pining_nocturne',0x0000000000000000005F000000000000000000000000,1,0,@ELEMENT_FIRE,0,4,@SKILL_SINGING,0,2000,24000,237,268,295,2000,0,0,1.00,20,140,0,204,'ABYSSEA'); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index a2863464055..7f8416672e5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -16,6 +16,7 @@ set(COMMON_SOURCES $<$:${CMAKE_CURRENT_SOURCE_DIR}/debug_linux.cpp> $<$:${CMAKE_CURRENT_SOURCE_DIR}/debug_osx.cpp> $<$:${CMAKE_CURRENT_SOURCE_DIR}/debug_windows.cpp> + ${CMAKE_CURRENT_SOURCE_DIR}/earth_time.h ${CMAKE_CURRENT_SOURCE_DIR}/filewatcher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/filewatcher.h ${CMAKE_CURRENT_SOURCE_DIR}/ipp.cpp @@ -34,7 +35,6 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/string.h ${CMAKE_CURRENT_SOURCE_DIR}/task_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/task_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/timer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timer.h ${CMAKE_CURRENT_SOURCE_DIR}/tracy.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tracy.h @@ -44,7 +44,6 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/utils.h ${CMAKE_CURRENT_SOURCE_DIR}/uuid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/uuid.h - ${CMAKE_CURRENT_SOURCE_DIR}/vana_time.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vana_time.h ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp # auto-generated ${CMAKE_CURRENT_SOURCE_DIR}/version.h diff --git a/src/common/WheatyExceptionReport.cpp b/src/common/WheatyExceptionReport.cpp index 2e09a47c744..0bf0f83018a 100644 --- a/src/common/WheatyExceptionReport.cpp +++ b/src/common/WheatyExceptionReport.cpp @@ -15,6 +15,7 @@ #include "cbasetypes.h" #include "logging.h" #include "utils.h" +#include "timer.h" #include "version.h" #ifdef __clang__ @@ -103,7 +104,7 @@ bool WheatyExceptionReport::alreadyCrashed; std::mutex WheatyExceptionReport::alreadyCrashedLock; WheatyExceptionReport::pRtlGetVersion WheatyExceptionReport::RtlGetVersion; -time_point gStartUpTime = server_clock::now(); +timer::time_point gStartUpTime = timer::now(); std::string gUptimeString; std::string gCrashDateString; std::string gProcessMemoryUsageString; @@ -149,18 +150,18 @@ WheatyExceptionReport::~WheatyExceptionReport() const char* GetUptimeString() { - auto uptimeDuration = server_clock::now() - gStartUpTime; - if (uptimeDuration < std::chrono::minutes(2)) + auto uptimeDuration = timer::now() - gStartUpTime; + if (uptimeDuration < 2min) { - gUptimeString = fmt::format("{} seconds", std::chrono::duration_cast(uptimeDuration).count()).c_str(); + gUptimeString = fmt::format("{} seconds", std::chrono::floor(uptimeDuration).count()).c_str(); } - else if (uptimeDuration > std::chrono::minutes(120)) + else if (uptimeDuration > 2h) { - gUptimeString = fmt::format("{} hours", std::chrono::duration_cast(uptimeDuration).count()).c_str(); + gUptimeString = fmt::format("{} hours", std::chrono::floor(uptimeDuration).count()).c_str(); } else { - gUptimeString = fmt::format("{} minutes", std::chrono::duration_cast(uptimeDuration).count()).c_str(); + gUptimeString = fmt::format("{} minutes", std::chrono::floor(uptimeDuration).count()).c_str(); } return gUptimeString.c_str(); @@ -372,8 +373,7 @@ LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( Log(_T("Process Name: %s"), GetCommandLineArgsString()); Log(_T("Full crash report: %s"), m_szLogFileName); Log(_T("Memory dump: %s"), m_szDumpFileName); - std::time_t t = std::time(nullptr); - Log(_T(fmt::format("Time of crash: {:%Y/%m/%d %H:%M:%S}", fmt::localtime(t)).c_str())); + Log(_T(fmt::format("Time of crash: {:%Y/%m/%d %H:%M:%S}", earth_time::to_local_tm()).c_str())); Log(_T("Process Uptime: %s"), GetUptimeString()); PrintSystemInfo(); Log(_T("Process Memory Usage: %s"), GetProcessMemoryUsageString()); @@ -401,7 +401,7 @@ LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( m_hReportFile = nullptr; // Pause for a moment to give spdlog a chance to flush - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(200ms); TerminateProcess(GetCurrentProcess(), 1); return EXCEPTION_EXECUTE_HANDLER; // Unreacheable code diff --git a/src/common/application.cpp b/src/common/application.cpp index 7b0788c835a..95f6b039ec3 100644 --- a/src/common/application.cpp +++ b/src/common/application.cpp @@ -100,7 +100,6 @@ Application::Application(std::string const& serverName, int argc, char** argv) // TODO: How much of this interferes with the signal handler in here? debug::init(); - timer_init(); lua_init(); settings::init(); @@ -112,7 +111,7 @@ Application::Application(std::string const& serverName, int argc, char** argv) ShowInfoFmt("======================================================================="); ShowInfoFmt("Begin {}-server init...", serverName); - srand((uint32)time(nullptr)); + srand(earth_time::timestamp()); xirand::seed(); #ifdef ENV64BIT @@ -165,7 +164,7 @@ void Application::usercheck() { std::cerr << "You are running as the root superuser or admin.\n"; std::cerr << "It is unnecessary and unsafe to run with root privileges.\n"; - std::this_thread::sleep_for(std::chrono::seconds(5)); + std::this_thread::sleep_for(5s); } #endif // TRACY_ENABLE } diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index 0effc777d1f..fa303d45ea3 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -73,14 +73,6 @@ inline void destroy_arr(T*& ptr) } using namespace std::literals::chrono_literals; -using server_clock = std::chrono::system_clock; -using time_point = server_clock::time_point; -using duration = server_clock::duration; - -// Not used so as not to accidentally mix with server_clock -// using hires_clock = std::chrono::high_resolution_clock; -// using hires_time_point = hires_clock::time_point; -// using hires_duration = hires_clock::duration; template using MinHeap = std::priority_queue, std::greater>; diff --git a/src/common/database.cpp b/src/common/database.cpp index d62ffa58fae..73a87a3b679 100644 --- a/src/common/database.cpp +++ b/src/common/database.cpp @@ -26,6 +26,7 @@ #include "macros.h" #include "settings.h" #include "task_manager.h" +#include "timer.h" #include "utils.h" #include @@ -215,11 +216,11 @@ Synchronized& db::detail::getState() auto db::detail::timer(std::string const& query) -> xi::final_action> { // clang-format off - const auto start = server_clock::now(); + const auto start = timer::now(); return xi::finally>([query, start]() -> void { - const auto end = server_clock::now(); - const auto duration = std::chrono::duration_cast(end - start).count(); + const auto end = timer::now(); + const auto duration = timer::count_milliseconds(end - start); if (timersEnabled && settings::get("logging.SQL_SLOW_QUERY_LOG_ENABLE")) { if (duration > settings::get("logging.SQL_SLOW_QUERY_ERROR_TIME")) @@ -302,7 +303,7 @@ auto db::queryStr(std::string const& rawQuery) -> std::unique_ptr +#include + +#include "cbasetypes.h" + +namespace earth_time +{ + // Base clock for wall-clock time (UTC) + using clock = std::chrono::system_clock; + using duration = clock::duration; + using time_point = clock::time_point; + + // Unix time of the Vana'diel epoch + static constexpr earth_time::time_point vanadiel_epoch{ 1009810800s }; + + // Earth time = UTC + inline time_point now() + { + return clock::now(); + } + + inline std::tm to_utc_tm(const time_point& tp = clock::now()) + { + std::time_t time_t_val = clock::to_time_t(tp); + std::tm utc_tm{}; + _gmtime_s(&utc_tm, &time_t_val); + return utc_tm; + } + + inline std::tm to_local_tm(const time_point& tp = clock::now()) + { + std::time_t time_t_val = clock::to_time_t(tp); + std::tm local_tm{}; + _localtime_s(&local_tm, &time_t_val); + return local_tm; + } + + namespace utc + { + // seconds after the minute - [​0​, 60] + inline uint32 get_second(const time_point& tp = now()) + { + const auto days = std::chrono::floor(tp); + const auto time = std::chrono::hh_mm_ss(tp - days); + return static_cast(time.seconds().count()); + } + // minutes after the hour – [​0​, 59] + inline uint32 get_minute(const time_point& tp = now()) + { + const auto days = std::chrono::floor(tp); + const auto time = std::chrono::hh_mm_ss(tp - days); + return static_cast(time.minutes().count()); + } + // hours since midnight – [​0​, 23] + inline uint32 get_hour(const time_point& tp = now()) + { + const auto days = std::chrono::floor(tp); + const auto time = std::chrono::hh_mm_ss(tp - days); + return static_cast(time.hours().count()); + } + // day of the month – [1, 31] + inline uint32 get_monthday(const time_point& tp = now()) + { + const auto ymd = std::chrono::year_month_day(std::chrono::floor(tp)); + return static_cast(ymd.day()); + } + // current month – [​1​, 12] + inline uint32 get_month(const time_point& tp = now()) + { + const auto ymd = std::chrono::year_month_day(std::chrono::floor(tp)); + return static_cast(ymd.month()); + } + // current year + inline int32 get_year(const time_point& tp = now()) + { + const auto ymd = std::chrono::year_month_day(std::chrono::floor(tp)); + return static_cast(ymd.year()); + } + // days since Sunday – [​0​, 6] + inline uint32 get_weekday(const time_point& tp = now()) + { + return std::chrono::weekday(std::chrono::floor(tp)).c_encoding(); + } + // days since January 1 – [​0​, 365] + inline uint32 get_yearday(const time_point& tp = now()) + { + const auto years = std::chrono::floor(tp); + const auto days = std::chrono::floor(tp - years); + return static_cast(days.count()); + } + + inline time_point get_next_midnight(const time_point& tp = now()) + { + return std::chrono::ceil(tp); + } + } // namespace utc + + // https://github.com/llvm/llvm-project/issues/99982 + // Japan Standard Time (UTC+9) + namespace jst + { + // seconds after the minute - [​0​, 60] + inline uint32 get_second(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto days = std::chrono::floor(jst_tp); + const auto time = std::chrono::hh_mm_ss(jst_tp - days); + return static_cast(time.seconds().count()); + } + // minutes after the hour – [​0​, 59] + inline uint32 get_minute(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto days = std::chrono::floor(jst_tp); + const auto time = std::chrono::hh_mm_ss(jst_tp - days); + return static_cast(time.minutes().count()); + } + // hours since midnight – [​0​, 23] + inline uint32 get_hour(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto days = std::chrono::floor(jst_tp); + const auto time = std::chrono::hh_mm_ss(jst_tp - days); + return static_cast(time.hours().count()); + } + // day of the month – [1, 31] + inline uint32 get_monthday(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto ymd = std::chrono::year_month_day(std::chrono::floor(jst_tp)); + return static_cast(ymd.day()); + } + // current month – [​1​, 12] + inline uint32 get_month(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto ymd = std::chrono::year_month_day(std::chrono::floor(jst_tp)); + return static_cast(ymd.month()); + } + // current year + inline int32 get_year(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto ymd = std::chrono::year_month_day(std::chrono::floor(jst_tp)); + return static_cast(ymd.year()); + } + // days since Sunday – [​0​, 6] + inline uint32 get_weekday(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + return std::chrono::weekday(std::chrono::floor(jst_tp)).c_encoding(); + } + // days since January 1 – [​0​, 365] + inline uint32 get_yearday(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + const auto jst_tp = time_point(tp + 9h); + const auto years = std::chrono::floor(jst_tp); + const auto days = std::chrono::floor(jst_tp - years); + return static_cast(days.count()); + } + + inline time_point get_next_midnight(const time_point& tp = now()) + { + // const auto jst_tp = std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), tp).get_local_time(); + // const auto jst_midnight = std::chrono::ceil(jst_tp); + // return std::chrono::zoned_time(std::chrono::locate_zone("Asia/Tokyo"), jst_midnight).get_sys_time(); + return utc::get_next_midnight(tp + 9h) - 9h; + } + } // namespace jst + + namespace local + { + // seconds after the minute - [​0​, 60] + inline uint32 get_second(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto days = std::chrono::floor(local_tp); + // const auto time = std::chrono::hh_mm_ss(local_tp - days); + // return static_cast(time.seconds().count()); + return to_local_tm(tp).tm_sec; + } + // minutes after the hour – [​0​, 59] + inline uint32 get_minute(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto days = std::chrono::floor(local_tp); + // const auto time = std::chrono::hh_mm_ss(local_tp - days); + // return static_cast(time.minutes().count()); + return to_local_tm(tp).tm_min; + } + // hours since midnight – [​0​, 23] + inline uint32 get_hour(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto days = std::chrono::floor(local_tp); + // const auto time = std::chrono::hh_mm_ss(local_tp - days); + // return static_cast(time.hours().count()); + return to_local_tm(tp).tm_hour; + } + // day of the month – [1, 31] + inline uint32 get_monthday(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto ymd = std::chrono::year_month_day(std::chrono::floor(local_tp)); + // return static_cast(ymd.day()); + return to_local_tm(tp).tm_mday; + } + // current month – [​1​, 12] + inline uint32 get_month(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto ymd = std::chrono::year_month_day(std::chrono::floor(local_tp)); + // return static_cast(ymd.month()); + return to_local_tm(tp).tm_mon + 1; + } + // current year + inline int32 get_year(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto ymd = std::chrono::year_month_day(std::chrono::floor(local_tp)); + // return static_cast(ymd.year()); + return to_local_tm(tp).tm_year + 1900; + } + // days since Sunday – [​0​, 6] + inline uint32 get_weekday(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // return std::chrono::weekday(std::chrono::floor(local_tp)).c_encoding(); + return to_local_tm(tp).tm_wday; + } + // days since January 1 – [​0​, 365] + inline uint32 get_yearday(const time_point& tp = now()) + { + // const auto local_tp = std::chrono::zoned_time(std::chrono::current_zone(), tp).get_local_time(); + // const auto years = std::chrono::floor(local_tp); + // const auto days = std::chrono::floor(local_tp - years); + // return static_cast(days.count()); + return to_local_tm(tp).tm_yday; + } + inline bool is_dst(const time_point& tp = now()) + { + // const auto sys_info = std::chrono::current_zone()->get_info(tp); + // return sys_info.save != 0min; + return to_local_tm(tp).tm_isdst > 0; + } + } // namespace local + + // Returns a Unix timestamp. + inline uint32 timestamp(const time_point& tp = now()) + { + return static_cast(std::chrono::floor(tp.time_since_epoch()).count()); + } + + // Returns the number of Earth seconds since the Vana'diel epoch. + inline uint32 vanadiel_timestamp(const time_point& tp = now()) + { + return static_cast(std::chrono::floor(tp - vanadiel_epoch).count()); + } + + // Returns an integer 0-6 representing Monday-Sunday JST. + inline uint8 get_game_weekday(const time_point& tp = now()) + { + return static_cast(std::chrono::weekday(jst::get_weekday(tp)).iso_encoding() - 1); + } + + // Returns a time point for the start of the next game week (midnight Monday JST aka weekly reset). + inline time_point get_next_game_week(const time_point& tp = now()) + { + // Start with the next midnight and apply N days worth of time to it. + return jst::get_next_midnight(tp) + std::chrono::days(6 - get_game_weekday(tp)); + } +}; // namespace earth_time diff --git a/src/common/ipp.h b/src/common/ipp.h index bebb943cc7a..b4207c265bb 100644 --- a/src/common/ipp.h +++ b/src/common/ipp.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include diff --git a/src/common/logging.cpp b/src/common/logging.cpp index f1bb88e0150..d3f571d7232 100755 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -135,7 +135,7 @@ void logging::InitializeLog(std::string const& serverName, std::string const& lo // If you create more than one worker thread, messages may be delivered out of order spdlog::init_thread_pool(8192, 1); spdlog::flush_on(spdlog::level::warn); - spdlog::flush_every(std::chrono::seconds(5)); + spdlog::flush_every(5s); // Sink to console std::vector sinks; diff --git a/src/common/mmo.h b/src/common/mmo.h index 770ed694e1b..0c015d619df 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -22,13 +22,13 @@ #pragma once #include "cbasetypes.h" +#include "timer.h" #include "xi.h" #include #include #include #include -#include #include #define FFXI_HEADER_SIZE 0x1C // common packet header size @@ -316,9 +316,9 @@ struct eminencelog_t struct eminencecache_t { - xi::bitset<4096> activemap; - uint32 lastWriteout; - bool notifyTimedRecord; + xi::bitset<4096> activemap; + timer::time_point lastWriteout; + bool notifyTimedRecord; }; struct nameflags_t @@ -350,9 +350,9 @@ struct bazaar_t struct pathpoint_t { - position_t position; - uint32 wait; - bool setRotation; + position_t position; + timer::duration wait; + bool setRotation; }; // A comment on the packets below, defined as macros. diff --git a/src/common/sql.cpp b/src/common/sql.cpp index 3a6f608703a..4676af3d099 100644 --- a/src/common/sql.cpp +++ b/src/common/sql.cpp @@ -46,7 +46,8 @@ SqlConnection::SqlConnection() } SqlConnection::SqlConnection(const char* user, const char* passwd, const char* host, uint16 port, const char* db) -: m_ThreadId(std::this_thread::get_id()) +: m_PingInterval(0s) +, m_ThreadId(std::this_thread::get_id()) { TracyZoneScoped; @@ -80,8 +81,8 @@ SqlConnection::SqlConnection(const char* user, const char* passwd, const char* h m_Db = db; // these members will be set up in SetupKeepalive(), they need to be init'd here to appease clang-tidy - m_PingInterval = 0; - m_LastPing = 0; + m_PingInterval = 0s; + m_LastPing = timer::time_point::min(); m_TimersEnabled = false; @@ -152,9 +153,7 @@ int32 SqlConnection::SetEncoding(const char* encoding) void SqlConnection::SetupKeepalive() { TracyZoneScoped; - auto now = std::chrono::system_clock::now().time_since_epoch(); - auto nowSeconds = std::chrono::duration_cast(now).count(); - m_LastPing = nowSeconds; + m_LastPing = timer::now(); // set a default value first uint32 timeout = 7200; // 2 hours @@ -169,7 +168,7 @@ void SqlConnection::SetupKeepalive() // 30-second reserve uint8 reserve = 30; - m_PingInterval = timeout + reserve; + m_PingInterval = std::chrono::seconds(timeout + reserve); } void SqlConnection::EnableTimers() @@ -179,14 +178,13 @@ void SqlConnection::EnableTimers() int32 SqlConnection::TryPing() { TracyZoneScoped; - auto now = std::chrono::system_clock::now().time_since_epoch(); - auto nowSeconds = std::chrono::duration_cast(now).count(); + auto now = timer::now(); - if (m_LastPing + m_PingInterval <= nowSeconds) + if (m_LastPing + m_PingInterval <= now) { ShowInfo("(C) Pinging SQL server to keep connection alive"); - m_LastPing = nowSeconds; + m_LastPing = now; auto startId = mysql_thread_id(&self->handle); try @@ -236,7 +234,7 @@ int32 SqlConnection::QueryStr(const char* query) FreeResult(); self->buf.clear(); - auto startTime = server_clock::now(); + auto startTime = timer::now(); { self->buf += query; @@ -258,18 +256,18 @@ int32 SqlConnection::QueryStr(const char* query) } } - auto endTime = server_clock::now(); - auto dTime = std::chrono::duration_cast(endTime - startTime); + auto endTime = timer::now(); + auto dTimeMs = timer::count_milliseconds(endTime - startTime); if (m_TimersEnabled && settings::get("logging.SQL_SLOW_QUERY_LOG_ENABLE")) { - if (dTime > std::chrono::milliseconds(settings::get("logging.SQL_SLOW_QUERY_ERROR_TIME"))) + if (dTimeMs > settings::get("logging.SQL_SLOW_QUERY_ERROR_TIME")) { - ShowError(fmt::format("SQL query took {}ms: {}", dTime.count(), self->buf)); + ShowError(fmt::format("SQL query took {}ms: {}", dTimeMs, self->buf)); } - else if (dTime > std::chrono::milliseconds(settings::get("logging.SQL_SLOW_QUERY_WARNING_TIME"))) + else if (dTimeMs > settings::get("logging.SQL_SLOW_QUERY_WARNING_TIME")) { - ShowWarning(fmt::format("SQL query took {}ms: {}", dTime.count(), self->buf)); + ShowWarning(fmt::format("SQL query took {}ms: {}", dTimeMs, self->buf)); } } diff --git a/src/common/sql.h b/src/common/sql.h index 8819b2ef52a..a77fbc8ed30 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -22,6 +22,7 @@ #pragma once #include "cbasetypes.h" +#include "timer.h" #include #include @@ -207,8 +208,8 @@ class SqlConnection uint16 m_Port; const char* m_Db; - uint32 m_PingInterval; - uint32 m_LastPing; + timer::duration m_PingInterval; + timer::time_point m_LastPing; std::thread::id m_ThreadId; diff --git a/src/common/task_manager.cpp b/src/common/task_manager.cpp index d24cf901c6d..a8e89c57233 100644 --- a/src/common/task_manager.cpp +++ b/src/common/task_manager.cpp @@ -23,7 +23,6 @@ #include "common/logging.h" #include "common/task_manager.h" -#include "common/timer.h" #include "common/tracy.h" #include "common/utils.h" @@ -84,13 +83,13 @@ void CTaskManager::RemoveTask(std::string const& TaskName) m_TaskList = newPq; } -duration CTaskManager::doExpiredTasks(time_point tick) // tick is normally server_clock::now() +timer::duration CTaskManager::doExpiredTasks(timer::time_point tick) // tick is normally timer::now() { TracyZoneScoped; - const auto start = server_clock::now(); + const auto start = timer::now(); - duration diff = 1s; + timer::duration diff = 1s; while (!m_TaskList.empty()) { CTask* PTask = m_TaskList.top(); @@ -127,6 +126,5 @@ duration CTaskManager::doExpiredTasks(time_point tick) // tick is normally serve } } - // We clamp with a minimum to ensure that the network phase doesn't starve - return std::clamp(server_clock::now() - start, 50ms, 1000ms); + return timer::now() - start; } diff --git a/src/common/task_manager.h b/src/common/task_manager.h index ccbd663da84..573d4fddce9 100644 --- a/src/common/task_manager.h +++ b/src/common/task_manager.h @@ -23,6 +23,7 @@ #include "cbasetypes.h" #include "singleton.h" +#include "timer.h" #include #include @@ -42,7 +43,7 @@ class CTaskManager : public Singleton TASK_INVALID }; - using TaskFunc_t = std::function; + using TaskFunc_t = std::function; template struct greater_equal @@ -59,7 +60,7 @@ class CTaskManager : public Singleton { public: template - CTask(std::string const& name, time_point tick, std::any data, TASKTYPE type, duration interval, F&& func) + CTask(std::string const& name, timer::time_point tick, std::any data, TASKTYPE type, timer::duration interval, F&& func) : m_name(name) , m_type(type) , m_tick(tick) @@ -69,12 +70,12 @@ class CTaskManager : public Singleton { } - std::string m_name; - TASKTYPE m_type; - time_point m_tick; - duration m_interval; - std::any m_data; - TaskFunc_t m_func; + std::string m_name; + TASKTYPE m_type; + timer::time_point m_tick; + timer::duration m_interval; + std::any m_data; + TaskFunc_t m_func; }; ~CTaskManager(); @@ -87,12 +88,12 @@ class CTaskManager : public Singleton CTask* AddTask(CTask*); template - CTask* AddTask(std::string const& InitName, time_point InitTick, std::any InitData, TASKTYPE InitType, duration InitInterval, F&& InitFunc) + CTask* AddTask(std::string const& InitName, timer::time_point InitTick, std::any InitData, TASKTYPE InitType, timer::duration InitInterval, F&& InitFunc) { return AddTask(new CTask(InitName, InitTick, InitData, InitType, InitInterval, std::forward(InitFunc))); } - auto doExpiredTasks(time_point tick) -> duration; + auto doExpiredTasks(timer::time_point tick) -> timer::duration; void RemoveTask(std::string const& TaskName); protected: diff --git a/src/common/timer.cpp b/src/common/timer.cpp deleted file mode 100644 index e254eebbffc..00000000000 --- a/src/common/timer.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -=========================================================================== - - Copyright (c) 2010-2015 Darkstar Dev Teams - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see http://www.gnu.org/licenses/ - -=========================================================================== -*/ - -#include "common/timer.h" -#include "common/logging.h" -#include "common/utils.h" - -#include -#include -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include // GetTickCount() -#else -#include // struct timeval, gettimeofday() -#include -#endif - -// server startup time -time_point start_time; - -/*---------------------------- - * Get tick time - *----------------------------*/ - -#if defined(ENABLE_RDTSC) -static uint64 RDTSC_BEGINTICK = 0, RDTSC_CLOCK = 0; - -static __inline uint64 _rdtsc() -{ - // clang-format off - register union - { - uint64 qw; - uint32 dw[2]; - } t; - - asm volatile("rdtsc" : "=a"(t.dw[0]), "=d"(t.dw[1])); - // clang-format on - - return t.qw; -} - -static void rdtsc_calibrate() -{ - uint64 t1, t2; - int32 i; - - ShowInfo("Calibrating Timer Source, please wait... "); - - RDTSC_CLOCK = 0; - - for (i = 0; i < 5; i++) - { - t1 = _rdtsc(); - usleep(1000000); // 1000 MS - t2 = _rdtsc(); - RDTSC_CLOCK += (t2 - t1) / 1000; - } - RDTSC_CLOCK /= 5; - - RDTSC_BEGINTICK = _rdtsc(); - - ShowInfo(" done. (Frequency: %u Mhz)", (uint32)(RDTSC_CLOCK / 1000)); -} -#endif - -/// platform-abstracted tick retrieval -static uint32 tick() -{ -#if defined(WIN32) - return GetTickCount(); -#elif defined(ENABLE_RDTSC) - // - return (uint32)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); - // -#elif (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) /* posix compliant */) || \ - (defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 500005 /* FreeBSD >= 5.1.0 */) - timespec tval{}; - clock_gettime(CLOCK_MONOTONIC, &tval); - return tval.tv_sec * 1000 + tval.tv_nsec / 1000000; -#else - timeval tval{}; - gettimeofday(&tval, nullptr); - return tval.tv_sec * 1000 + tval.tv_usec / 1000; -#endif -} - -////////////////////////////////////////////////////////////////////////// -#if defined(TICK_CACHE) && TICK_CACHE > 1 -////////////////////////////////////////////////////////////////////////// -// tick is cached for TICK_CACHE calls -static uint32 gettick_cache; -static int32 gettick_count = 1; - -unsigned int gettick_nocache(void) -{ - gettick_count = TICK_CACHE; - gettick_cache = tick(); - return gettick_cache; -} - -unsigned int gettick(void) -{ - return (--gettick_count == 0) ? gettick_nocache() : gettick_cache; -} -////////////////////////////// -#else -////////////////////////////// -// tick doesn't get cached -uint32 gettick_nocache() -{ - return tick() + 100000000; // +27 hours for respawn -} - -uint32 gettick() -{ - return tick() + 100000000; // +27 hours for respawn -} -////////////////////////////////////////////////////////////////////////// -#endif -///////////////////////////////////////////////////////////////////////// - -duration get_uptime() -{ - return server_clock::now() - start_time; -} - -void timer_init() -{ -#if defined(ENABLE_RDTSC) - rdtsc_calibrate(); -#endif - start_time = server_clock::now(); -} - -void timer_final() -{ -} - -time_point get_server_start_time() -{ - return start_time; -} - -uint32 getCurrentTimeMs() -{ - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() % 1000; -} - -auto getMilliseconds(const duration& d) -> int64 -{ - return std::chrono::duration_cast(d).count(); -}; diff --git a/src/common/timer.h b/src/common/timer.h index ac4995b5c94..356ca748153 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -2,6 +2,7 @@ =========================================================================== Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2025 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,16 +22,58 @@ #pragma once -#include "common/cbasetypes.h" +#include -uint32 gettick(void); -uint32 gettick_nocache(void); +#include "cbasetypes.h" +#include "earth_time.h" -time_point get_server_start_time(void); +namespace timer +{ + // This clock is not stable across reboots. + // Use earth_time if you need real time. + // Use timer::to_utc/timer::from_utc to persist timestamps to the database (status effects). + using clock = std::chrono::steady_clock; + using duration = clock::duration; + using time_point = clock::time_point; -void timer_init(void); -void timer_final(void); + inline const time_point start_time = clock::now(); -uint32 getCurrentTimeMs(); + inline time_point now() + { + return clock::now(); + } -auto getMilliseconds(const duration& d) -> int64; + inline duration get_uptime() + { + return clock::now() - start_time; + } + + // https://stackoverflow.com/questions/35282308/convert-between-c11-clocks/35282833#35282833 + inline earth_time::time_point to_utc(const time_point& timer_tp = now()) + { + auto utc_now = earth_time::now(); + auto timer_now = clock::now(); + return std::chrono::time_point_cast(timer_tp - timer_now + utc_now); + }; + + inline time_point from_utc(const earth_time::time_point& utc_tp = earth_time::now()) + { + auto timer_now = clock::now(); + auto utc_now = earth_time::now(); + return utc_tp - utc_now + timer_now; + }; + + // Gets the Earth milliseconds of a duration. + template + auto count_milliseconds(const std::chrono::duration& d) -> int64 + { + return std::chrono::floor(d).count(); + }; + + // Gets the Earth seconds of a duration. + template + auto count_seconds(const std::chrono::duration& d) -> int64 + { + return std::chrono::floor(d).count(); + }; +}; // namespace timer diff --git a/src/common/utils.h b/src/common/utils.h index 1046270bf8d..dab8c2b97d7 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -28,6 +28,7 @@ #include "common/sql.h" #include "common/stdext.h" #include "common/synchronized.h" +#include "common/timer.h" #include "common/xirand.h" // Ahead of (not ) @@ -38,7 +39,6 @@ #include #include -#include #include #include #include @@ -210,10 +210,10 @@ namespace utils } // namespace utils // clang-format off -static Synchronized> lastExecutionTimes; +static Synchronized> lastExecutionTimes; #define RATE_LIMIT(duration, code) \ { \ - const auto currentTime = server_clock::now(); \ + const auto currentTime = timer::now(); \ const auto key = std::string(__FILE__) + ":" + std::to_string(__LINE__); \ lastExecutionTimes.write([&](auto& lastExecutionTimes) \ { \ diff --git a/src/common/vana_time.cpp b/src/common/vana_time.cpp deleted file mode 100644 index 4e8ce65c6fb..00000000000 --- a/src/common/vana_time.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* -=========================================================================== - - Copyright (c) 2010-2015 Darkstar Dev Teams - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see http://www.gnu.org/licenses/ - -=========================================================================== -*/ - -#include "logging.h" - -#include - -#include "vana_time.h" - -CVanaTime::CVanaTime() -{ - setCustomEpoch(0); -} - -uint32 CVanaTime::getDate() const -{ - return m_vanaDate; -} - -uint32 CVanaTime::getYear() const -{ - return m_vYear; -} - -uint32 CVanaTime::getMonth() const -{ - return m_vMon; -} - -uint32 CVanaTime::getDayOfTheMonth() const -{ - return m_vDate; -} - -uint32 CVanaTime::getHour() const -{ - return m_vHour; -} - -uint32 CVanaTime::getMinute() const -{ - return m_vMin; -} - -uint32 CVanaTime::getWeekday() const -{ - return m_vDay; -} - -uint32 CVanaTime::getSysTime() -{ - return static_cast(time(nullptr)); -} - -uint32 CVanaTime::getSysHour() -{ - time_t now = time(nullptr); - tm ltm{}; - - _localtime_s(<m, &now); - - return ltm.tm_hour; -} - -uint32 CVanaTime::getSysMinute() -{ - time_t now = time(nullptr); - tm ltm{}; - - _localtime_s(<m, &now); - - return ltm.tm_min; -} - -uint32 CVanaTime::getSysSecond() -{ - time_t now = time(nullptr); - tm ltm{}; - - _localtime_s(<m, &now); - - return ltm.tm_sec; -} - -uint32 CVanaTime::getSysWeekDay() -{ - time_t now = time(nullptr); - tm ltm{}; - - _localtime_s(<m, &now); - - return ltm.tm_wday; -} - -uint32 CVanaTime::getSysYearDay() -{ - time_t now = time(nullptr); - tm ltm{}; - - _localtime_s(<m, &now); - - return ltm.tm_yday; -} - -uint32 CVanaTime::getJstHour() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_hour; -} - -uint32 CVanaTime::getJstMinute() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_min; -} - -uint32 CVanaTime::getJstSecond() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_sec; -} - -uint32 CVanaTime::getJstWeekDay() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_wday; -} - -uint32 CVanaTime::getJstDayOfMonth() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_mday; -} - -uint32 CVanaTime::getJstYearDay() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jtm{}; - - _gmtime_s(&jtm, &now); - - return jtm.tm_yday; -} - -uint32 CVanaTime::getJstMidnight() -{ - auto now = time(nullptr) + JST_OFFSET; - tm jst{}; - - _gmtime_s(&jst, &now); - - jst.tm_hour = 0; - jst.tm_min = 0; - jst.tm_sec = 0; - - return static_cast(timegm(&jst) - JST_OFFSET + (60 * 60 * 24)); // Unix timestamp of the upcoming JST midnight -} - -uint32 CVanaTime::getVanaTime() const -{ - // all functions/variables for in game time should be derived from this - return (uint32)time(nullptr) - (m_customEpoch ? m_customEpoch : VTIME_BASEDATE); -} - -uint32 CVanaTime::getEpoch() const -{ - return m_customEpoch ? m_customEpoch : VTIME_BASEDATE; -} - -uint32 CVanaTime::getCustomEpoch() const -{ - return m_customEpoch; -} - -void CVanaTime::setCustomEpoch(int32 epoch) -{ - m_customEpoch = epoch; - m_TimeType = SyncTime(); - - if (m_TimeType == TIME_NONE) // SyncTime wasn't on an exact hour, calculate current m_TimeType - { - switch (m_vHour) - { - case 23: - case 22: - case 21: - case 20: - m_TimeType = TIME_NIGHT; - break; - case 19: - case 18: - m_TimeType = TIME_EVENING; - break; - case 17: - m_TimeType = TIME_DUSK; - break; - case 16: - case 15: - case 14: - case 13: - case 12: - case 11: - case 10: - case 9: - case 8: - case 7: - m_TimeType = TIME_DAY; - break; - case 6: - m_TimeType = TIME_DAWN; - break; - case 5: - case 4: - m_TimeType = TIME_NEWDAY; - break; - case 3: - case 2: - case 1: - case 0: - m_TimeType = TIME_MIDNIGHT; - break; - } - } -} - -TIMETYPE CVanaTime::GetCurrentTOTD() -{ - return m_TimeType; -} - -uint32 CVanaTime::getMoonPhase() const -{ - int32 phase = 0; - double daysmod = (int32)(((m_vanaDate / VTIME_DAY) + 26) % 84); - - if (daysmod >= 42) - { - phase = (int32)(100 * ((daysmod - 42) / 42) + 0.5); - } - else - { - phase = (int32)(100 * (1 - (daysmod / 42)) + 0.5); - } - - return phase; -} - -uint8 CVanaTime::getMoonDirection() const -{ - double daysmod = (int32)(((m_vanaDate / VTIME_DAY) + 26) % 84); - - if (daysmod == 42 || daysmod == 0) - { - return 0; // neither waxing nor waning - } - else if (daysmod < 42) - { - return 1; // waning - } - else - { - return 2; // waxing - } -} - -uint8 CVanaTime::getRSERace() const -{ - return (uint8)(((m_vanaDate / VTIME_WEEK) - 22) % 8) + 1; -} - -uint8 CVanaTime::getRSELocation() const -{ - return (uint8)(((m_vanaDate / VTIME_WEEK) - 21) % 3); -} - -TIMETYPE CVanaTime::SyncTime() -{ - m_vanaDate = (uint32)(this->getVanaTime() / 60.0 * 25) + - 886 * VTIME_YEAR; // convert vana time (from SE epoch in earth seconds) to vanadiel minutes and add 886 vana years - - m_vYear = m_vanaDate / VTIME_YEAR; - m_vMon = (m_vanaDate / VTIME_MONTH) % 12 + 1; - m_vDate = (m_vanaDate / VTIME_DAY) % 30 + 1; - m_vDay = (m_vanaDate % VTIME_WEEK) / VTIME_DAY; - m_vHour = (m_vanaDate % VTIME_DAY) / VTIME_HOUR; - m_vMin = m_vanaDate % VTIME_HOUR; - - static uint8 lastTickedHour = m_vHour; - if (m_vHour == (lastTickedHour + 1) % 24u) - { - lastTickedHour = m_vHour; - switch (m_vHour) - { - case 0: - m_TimeType = TIME_MIDNIGHT; - return TIME_MIDNIGHT; - case 4: - m_TimeType = TIME_NEWDAY; - return TIME_NEWDAY; - case 6: - m_TimeType = TIME_DAWN; - return TIME_DAWN; - case 7: - m_TimeType = TIME_DAY; - return TIME_DAY; - case 17: - m_TimeType = TIME_DUSK; - return TIME_DUSK; - case 18: - m_TimeType = TIME_EVENING; - return TIME_EVENING; - case 20: - m_TimeType = TIME_NIGHT; - return TIME_NIGHT; - } - } - return TIME_NONE; -} diff --git a/src/common/vana_time.h b/src/common/vana_time.h index db6822b5887..6719665b2c6 100644 --- a/src/common/vana_time.h +++ b/src/common/vana_time.h @@ -1,7 +1,7 @@ /* =========================================================================== - Copyright (c) 2010-2015 Darkstar Dev Teams + Copyright (c) 2025 LandSandBoat Dev Teams This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,21 +21,10 @@ #pragma once -#ifdef _WIN32 -#define timegm _mkgmtime -#endif - -#define VTIME_BASEDATE 1009810800 // unix epoch - 1009810800 = se epoch (in earth seconds) -#define VTIME_YEAR 518400 // 360 * GameDay -#define VTIME_MONTH 43200 // 30 * GameDay -#define VTIME_WEEK 11520 // 8 * GameDay -#define VTIME_DAY 1440 // 24 hours * GameHour -#define VTIME_HOUR 60 // 60 minutes - -#define JST_OFFSET 32400 // JST +offset from UTC +#include #include "cbasetypes.h" -#include "singleton.h" +#include "xi.h" enum DAYTYPE : uint8 { @@ -49,68 +38,232 @@ enum DAYTYPE : uint8 DARKSDAY = 7 }; -enum TIMETYPE : uint8 +namespace vanadiel_time { - TIME_NONE = 0, - TIME_MIDNIGHT = 1, - TIME_NEWDAY = 2, - TIME_DAWN = 3, - TIME_DAY = 4, - TIME_DUSK = 5, - TIME_EVENING = 6, - TIME_NIGHT = 7 -}; + using clock = xi::vanadiel_clock; + using duration = clock::duration; + using time_point = clock::time_point; -class CVanaTime : public Singleton -{ -public: - TIMETYPE SyncTime(); - TIMETYPE GetCurrentTOTD(); - - uint32 getDate() const; - uint32 getYear() const; - uint32 getMonth() const; - uint32 getDayOfTheMonth() const; - uint32 getHour() const; - uint32 getMinute() const; - uint32 getWeekday() const; - uint32 getMoonPhase() const; - uint8 getMoonDirection() const; - uint8 getRSERace() const; - uint8 getRSELocation() const; - uint32 getSysTime(); - uint32 getSysHour(); - uint32 getSysMinute(); - uint32 getSysSecond(); - uint32 getSysWeekDay(); // Number of day since sunday - uint32 getSysYearDay(); // Number of day since 1st january - uint32 getJstHour(); - uint32 getJstMinute(); - uint32 getJstSecond(); - uint32 getJstWeekDay(); // Number of day since sunday - uint32 getJstDayOfMonth(); - uint32 getJstYearDay(); // Number of day since 1st january - uint32 getJstMidnight(); // Upcoming JST midnight in unix timestamp - - uint32 getVanaTime() const; - uint32 getEpoch() const; - uint32 getCustomEpoch() const; - - void setCustomEpoch(int32 epoch); - -protected: - CVanaTime(); - -private: - uint32 m_vYear{}; // Vanadiel Year - uint32 m_vMon{}; // Vanadiel Month - uint32 m_vDate{}; // Vanadiel Date (day of the month) - uint32 m_vHour{}; // Vanadiel Hour - uint32 m_vMin{}; // Vanadiel Minute - uint32 m_vDay{}; // Vanadiel day of the week (fire, earth, wind, water, ice, lightning, light, dark) - uint32 m_vanaDate{}; // Vanadiel time in integer format - - TIMETYPE m_TimeType{}; // The current type of time - - int32 m_customEpoch{}; // Custom epoch to use instead of VTIME_BASEDATE -}; + enum TOTD : uint8 + { + NONE = 0, + MIDNIGHT = 1, + NEWDAY = 2, + DAWN = 3, + DAY = 4, + DUSK = 5, + EVENING = 6, + NIGHT = 7 + }; + + inline time_point now() + { + return clock::now(); + } + + inline earth_time::time_point to_earth_time(const time_point& vanadiel_tp = now()) + { + const earth_time::duration earth_since_epoch = std::chrono::duration_cast(vanadiel_tp.time_since_epoch()); + return earth_time::time_point(earth_since_epoch + earth_time::vanadiel_epoch); + }; + + inline time_point from_earth_time(const earth_time::time_point& earth_tp = earth_time::now()) + { + const clock::duration vanadiel_since_epoch = std::chrono::duration_cast(earth_tp - earth_time::vanadiel_epoch); + return time_point(vanadiel_since_epoch); + }; + + inline uint32 count_weeks(const duration& d) + { + const clock::weeks total_weeks = std::chrono::floor(d); + return static_cast(total_weeks.count()); + } + + inline uint32 count_days(const duration& d) + { + const clock::days total_days = std::chrono::floor(d); + return static_cast(total_days.count()); + } + + // seconds after the minute - [​0​, 60] + inline uint32 get_second(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::minutes minutes = std::chrono::floor(since_epoch); + const clock::seconds seconds = std::chrono::floor(since_epoch); + return static_cast((seconds % minutes).count()); + } + // minutes after the hour – [​0​, 59] + inline uint32 get_minute(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::hours hours = std::chrono::floor(since_epoch); + const clock::minutes minutes = std::chrono::floor(since_epoch); + return static_cast((minutes % hours).count()); + } + // hours since midnight – [​0​, 23] + inline uint32 get_hour(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::days days = std::chrono::floor(since_epoch); + const clock::hours hours = std::chrono::floor(since_epoch); + return static_cast((hours % days).count()); + } + // day of the month – [1, 30] + inline uint32 get_monthday(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::months months = std::chrono::floor(since_epoch); + const clock::days days = std::chrono::ceil(since_epoch); + return static_cast((days % months).count()); + } + // current month – [​1​, 12] + inline uint32 get_month(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::years years = std::chrono::floor(since_epoch); + const clock::months months = std::chrono::ceil(since_epoch); + return static_cast((months % years).count()); + } + // years since 886 + inline int32 get_year(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::years years = std::chrono::floor(since_epoch); + return static_cast(years.count()); + } + // days since Firesday – [​0​, 7] + inline uint32 get_weekday(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::weeks weeks = std::chrono::floor(since_epoch); + const clock::days days = std::chrono::floor(since_epoch); + return static_cast((days % weeks).count()); + } + // days since 1st day of year – [​0​, 360] + inline uint32 get_yearday(const time_point& tp = now()) + { + const duration since_epoch = tp.time_since_epoch(); + const clock::years years = std::chrono::floor(since_epoch); + const clock::days days = std::chrono::floor(since_epoch); + return static_cast((days % years).count()); + } + + inline time_point get_next_midnight(const time_point& tp = now()) + { + return std::chrono::ceil(tp); + } + + /** + * Gets the time of the day for the current or given time point. + * @returns NONE, MIDNIGHT, NEWDAY, DAWN, DAY, DUSK, EVENING, NIGHT + */ + inline TOTD get_totd(const time_point& tp = now()) + { + switch (get_hour(tp)) + { + case 0: + case 1: + case 2: + case 3: + return TOTD::MIDNIGHT; + case 4: + case 5: + return TOTD::NEWDAY; + case 6: + return TOTD::DAWN; + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + return TOTD::DAY; + case 17: + return TOTD::DUSK; + case 18: + case 19: + return TOTD::EVENING; + case 20: + case 21: + case 22: + case 23: + return TOTD::NIGHT; + default: + return TOTD::NONE; + } + } + + namespace moon + { + inline uint32 get_phase(const time_point& tp = now()) + { + int32 phase = 0; + double daysmod = static_cast((count_days(tp.time_since_epoch() + clock::years(886)) + 26) % 84); + + if (daysmod >= 42) + { + phase = static_cast(100 * ((daysmod - 42) / 42) + 0.5); + } + else + { + phase = static_cast(100 * (1 - (daysmod / 42)) + 0.5); + } + + return phase; + } + + /** + * Gets the moon direction for the current or given time point. + * @returns + * ``` + * 0: Neither + * 1: Waning + * 2: Waxing + * ``` + */ + inline uint8 get_direction(const time_point& tp = now()) + { + double daysmod = static_cast((count_days(tp.time_since_epoch() + clock::years(886)) + 26) % 84); + + if (daysmod == 42 || daysmod == 0) + { + return 0; // neither waxing nor waning + } + else if (daysmod < 42) + { + return 1; // waning + } + else + { + return 2; // waxing + } + } + } // namespace moon + + namespace rse + { + inline uint8 get_race(const time_point& tp = now()) + { + return static_cast(count_weeks(tp.time_since_epoch()) % 8 + 1); + } + + /** + * Gets the RSE location for the current or given time point. + * @returns + * ``` + * 0: Ordelle's Caves + * 1: Gusgen Mines + * 2: Maze of Shakhrami + * ``` + */ + inline uint8 get_location(const time_point& tp = now()) + { + return static_cast(count_weeks(tp.time_since_epoch()) % 3); + } + } // namespace rse +}; // namespace vanadiel_time diff --git a/src/common/watchdog.cpp b/src/common/watchdog.cpp index 310312756bf..ff2f09cc586 100644 --- a/src/common/watchdog.cpp +++ b/src/common/watchdog.cpp @@ -21,10 +21,10 @@ #include "watchdog.h" -Watchdog::Watchdog(duration timeout, std::function callback) +Watchdog::Watchdog(timer::duration timeout, std::function callback) : m_timeout(timeout) , m_callback(std::move(callback)) -, m_lastUpdate(server_clock::now()) +, m_lastUpdate(timer::now()) , m_running(true) { m_watchdog = nonstd::jthread(&Watchdog::_innerFunc, this); @@ -45,14 +45,14 @@ void Watchdog::update() { std::unique_lock lock(m_bottleneck); - m_lastUpdate = server_clock::now(); + m_lastUpdate = timer::now(); } void Watchdog::_innerFunc() { std::unique_lock lock(m_bottleneck); - while ((server_clock::now() - m_lastUpdate) < m_timeout) + while ((timer::now() - m_lastUpdate) < m_timeout) { m_stopCondition.wait_for(lock, m_timeout); } diff --git a/src/common/watchdog.h b/src/common/watchdog.h index e8b696d2683..b8e82074bd1 100644 --- a/src/common/watchdog.h +++ b/src/common/watchdog.h @@ -22,6 +22,7 @@ #pragma once #include "cbasetypes.h" +#include "timer.h" #include #include @@ -33,7 +34,7 @@ class Watchdog final { public: - Watchdog(duration timeout, std::function callback); + Watchdog(timer::duration timeout, std::function callback); ~Watchdog(); void update(); @@ -43,9 +44,9 @@ class Watchdog final using voidFunc_t = std::function; - duration m_timeout; - voidFunc_t m_callback; - time_point m_lastUpdate; + timer::duration m_timeout; + voidFunc_t m_callback; + timer::time_point m_lastUpdate; nonstd::jthread m_watchdog; std::atomic_bool m_running; diff --git a/src/common/xi.h b/src/common/xi.h index 5424915401a..f7a2a722770 100644 --- a/src/common/xi.h +++ b/src/common/xi.h @@ -25,6 +25,8 @@ #include #include +#include "earth_time.h" + // The purpose of this namespace IS NOT to replace the C++ standard library. // // It is to provide convenience wrappers around common standard library types @@ -37,6 +39,40 @@ namespace xi { + class vanadiel_clock + { + private: + using millisecond_ratio = std::ratio<1, 25000>; // (1Vms/25000ms) * 1000Vms * 60Vs = 1 Vmin + using second_ratio = std::ratio_multiply>; + using minute_ratio = std::ratio_multiply>; // 2.4 Earth seconds + using hour_ratio = std::ratio_multiply>; // 60 Vana'diel minutes + using day_ratio = std::ratio_multiply>; // 24 Vana'diel hours + using week_ratio = std::ratio_multiply>; // 8 Vana'diel days + using month_ratio = std::ratio_multiply>; // 30 Vana'diel days + using year_ratio = std::ratio_multiply>; // 360 Vana'diel days + + public: + using milliseconds = std::chrono::duration; + using seconds = std::chrono::duration; + using minutes = std::chrono::duration; + using hours = std::chrono::duration; + using days = std::chrono::duration; + using weeks = std::chrono::duration; + using months = std::chrono::duration; + using years = std::chrono::duration; + + using duration = milliseconds; + using rep = duration::rep; + using period = duration::period; + using time_point = std::chrono::time_point; + static const bool is_steady = false; + + static time_point now() noexcept + { + return time_point{ std::chrono::duration_cast(earth_time::now() - earth_time::vanadiel_epoch) }; + } + }; + // A wrapper around std::optional to allow usage of object.apply([](auto& obj) { ... }); // https://en.cppreference.com/w/cpp/utility/optional template diff --git a/src/login/auth_session.cpp b/src/login/auth_session.cpp index 56993540084..54c024b4bb5 100644 --- a/src/login/auth_session.cpp +++ b/src/login/auth_session.cpp @@ -272,7 +272,7 @@ void auth_session::read_func() ref(buffer_.data(), 1) = accountID; unsigned char hash[16]; - uint32 hashData = std::time(nullptr) ^ getpid(); + uint32 hashData = earth_time::timestamp() ^ getpid(); md5(reinterpret_cast(&hashData), hash, sizeof(hashData)); std::memcpy(buffer_.data() + 5, hash, 16); @@ -280,7 +280,7 @@ void auth_session::read_func() auto& session = loginHelpers::get_authenticated_session(ipAddress, asStringFromUntrustedSource(hash, sizeof(hash))); session.accountID = accountID; - session.authorizedTime = server_clock::now(); + session.authorizedTime = timer::now(); } else if (status & ACCOUNT_STATUS_CODE::BANNED) { @@ -338,11 +338,7 @@ void auth_session::read_func() accid = (accid < 1000 ? 1000 : accid); // creating new account - time_t timecreate{}; - tm timecreateinfo{}; - - time(&timecreate); - _localtime_s(&timecreateinfo, &timecreate); + std::tm timecreateinfo = earth_time::to_local_tm(); char strtimecreate[128]; strftime(strtimecreate, sizeof(strtimecreate), "%Y:%m:%d %H:%M:%S", &timecreateinfo); diff --git a/src/login/connect_server.cpp b/src/login/connect_server.cpp index bdb472a73f0..6a5112d640d 100644 --- a/src/login/connect_server.cpp +++ b/src/login/connect_server.cpp @@ -21,6 +21,8 @@ #include "connect_server.h" +#include "common/timer.h" + namespace { auto getZMQEndpointString() -> std::string @@ -60,7 +62,7 @@ void ConnectServer::run() handler auth(io_context_, settings::get("network.LOGIN_AUTH_PORT"), zmqDealerWrapper_); handler view(io_context_, settings::get("network.LOGIN_VIEW_PORT"), zmqDealerWrapper_); handler data(io_context_, settings::get("network.LOGIN_DATA_PORT"), zmqDealerWrapper_); - asio::steady_timer cleanup_callback(io_context_, std::chrono::minutes(15)); + asio::steady_timer cleanup_callback(io_context_, 15min); cleanup_callback.async_wait(std::bind(&ConnectServer::periodicCleanup, this, std::placeholders::_1, &cleanup_callback)); @@ -133,7 +135,7 @@ void ConnectServer::periodicCleanup(const asio::error_code& error, asio::steady_ // If it's been 15 minutes, erase it from the session list if (!session.data_session && !session.view_session && - (server_clock::now() - session.authorizedTime) > std::chrono::minutes(15)) + timer::now() > session.authorizedTime + 15min) { sessionIterator = ipAddrIterator->second.erase(sessionIterator); } @@ -157,7 +159,7 @@ void ConnectServer::periodicCleanup(const asio::error_code& error, asio::steady_ if (Application::isRunning()) { // reset timer - timer->expires_at(timer->expiry() + std::chrono::minutes(15)); + timer->expires_at(timer->expiry() + 15min); timer->async_wait(std::bind(&ConnectServer::periodicCleanup, this, std::placeholders::_1, timer)); } } diff --git a/src/login/data_session.cpp b/src/login/data_session.cpp index 673c6543ae2..a9a93ea6c53 100644 --- a/src/login/data_session.cpp +++ b/src/login/data_session.cpp @@ -338,7 +338,7 @@ void data_session::read_func() hasActiveSession = true; } - uint64 exceptionTime = 0; + auto exceptionTime = earth_time::time_point::min(); const auto rset3 = db::preparedStmt("SELECT UNIX_TIMESTAMP(exception) " "FROM ip_exceptions " @@ -346,13 +346,13 @@ void data_session::read_func() session.accountID); if (rset3 && rset3->rowsCount() != 0 && rset3->next()) { - exceptionTime = rset3->get("UNIX_TIMESTAMP(exception)"); + exceptionTime = earth_time::time_point(std::chrono::seconds(rset3->get("UNIX_TIMESTAMP(exception)"))); } - const auto timeStamp = static_cast(std::chrono::duration_cast(server_clock::now().time_since_epoch()).count()); + const auto currentTime = earth_time::now(); const auto isNotMaint = !settings::get("login.MAINT_MODE"); const auto loginLimit = settings::get("login.LOGIN_LIMIT"); - const auto excepted = exceptionTime > timeStamp; + const auto excepted = exceptionTime > currentTime; const auto loginLimitOK = loginLimit == 0 || sessionCount < loginLimit || excepted; const auto isGM = gmlevel > 0; @@ -445,11 +445,7 @@ void data_session::read_func() if (settings::get("login.LOG_USER_IP")) { // Log clients IP info when player spawns into map server - - time_t rawtime{}; - tm convertedTime{}; - time(&rawtime); - _localtime_s(&convertedTime, &rawtime); + std::tm convertedTime = earth_time::to_local_tm(); char timeAndDate[128]; strftime(timeAndDate, sizeof(timeAndDate), "%Y:%m:%d %H:%M:%S", &convertedTime); diff --git a/src/login/session.h b/src/login/session.h index 8487555cda9..6703d03a71f 100644 --- a/src/login/session.h +++ b/src/login/session.h @@ -23,6 +23,8 @@ #include "handler_session.h" +#include "common/timer.h" + // Metadata about each session struct session_t { @@ -39,5 +41,5 @@ struct session_t bool justCreatedNewChar = false; bool versionMismatch = false; - std::chrono::time_point authorizedTime = server_clock::now(); + timer::time_point authorizedTime = timer::now(); }; diff --git a/src/map/ability.cpp b/src/map/ability.cpp index 5c92fc9bf31..6ee401f09b0 100644 --- a/src/map/ability.cpp +++ b/src/map/ability.cpp @@ -38,7 +38,7 @@ CAbility::CAbility(uint16 id) , m_validTarget(0) , m_addType(0) , m_message(0) -, m_recastTime(0) +, m_recastTime(0s) , m_recastId(0) , m_CE(0) , m_VE(0) @@ -143,12 +143,12 @@ void CAbility::setAnimationID(uint16 animationID) m_animationID = animationID; } -void CAbility::setAnimationTime(duration time) +void CAbility::setAnimationTime(timer::duration time) { m_animationTime = time; } -void CAbility::setCastTime(duration time) +void CAbility::setCastTime(timer::duration time) { m_castTime = time; } @@ -158,22 +158,22 @@ uint16 CAbility::getAnimationID() const return m_animationID; } -duration CAbility::getAnimationTime() +timer::duration CAbility::getAnimationTime() { return m_animationTime; } -duration CAbility::getCastTime() +timer::duration CAbility::getCastTime() { return m_castTime; } -void CAbility::setRecastTime(uint16 recastTime) +void CAbility::setRecastTime(timer::duration recastTime) { - m_recastTime = (uint16)(recastTime * settings::get("map.ABILITY_RECAST_MULTIPLIER")); + m_recastTime = std::chrono::floor(recastTime * settings::get("map.ABILITY_RECAST_MULTIPLIER")); } -uint16 CAbility::getRecastTime() const +timer::duration CAbility::getRecastTime() const { return m_recastTime; } @@ -399,7 +399,7 @@ namespace ability PAbility->setJob(static_cast(rset->get("job"))); PAbility->setLevel(rset->get("level")); PAbility->setValidTarget(rset->get("validTarget")); - PAbility->setRecastTime(rset->get("recastTime")); + PAbility->setRecastTime(std::chrono::seconds(rset->get("recastTime"))); PAbility->setMessage(rset->get("message1")); // Unused - message2 PAbility->setAnimationID(rset->get("animation")); @@ -435,7 +435,7 @@ namespace ability PCharge->job = static_cast(rset2->get("job")); PCharge->level = rset2->get("level"); PCharge->maxCharges = rset2->get("maxCharges"); - PCharge->chargeTime = rset2->get("chargeTime"); + PCharge->chargeTime = std::chrono::seconds(rset2->get("chargeTime")); PCharge->merit = rset2->get("meritModId"); PChargesList.emplace_back(std::move(PCharge)); diff --git a/src/map/ability.h b/src/map/ability.h index d40fb8b1e9f..85a7fa58135 100644 --- a/src/map/ability.h +++ b/src/map/ability.h @@ -678,12 +678,12 @@ enum ABILITY struct Charge_t { - uint16 ID; // recastId - JOBTYPE job; // job - uint8 level; // level - uint8 maxCharges; // maximum number of stored charges - uint32 chargeTime; // time required to restore one charge - uint16 merit; + uint16 ID; // recastId + JOBTYPE job; // job + uint8 level; // level + uint8 maxCharges; // maximum number of stored charges + timer::duration chargeTime; // time required to restore one charge + uint16 merit; }; /************************************************************************ @@ -701,40 +701,40 @@ class CAbility bool isAoE() const; bool isConal(); - uint16 getID() const; - uint16 getMobSkillID() const; - JOBTYPE getJob(); - uint8 getLevel() const; - uint16 getAnimationID() const; - duration getAnimationTime(); - duration getCastTime(); - float getRange() const; - uint8 getAOE() const; - uint16 getValidTarget() const; - uint16 getAddType() const; - uint16 getMessage() const; - uint16 getAoEMsg() const; - uint16 getRecastTime() const; - uint16 getRecastId() const; - int32 getCE() const; - int32 getVE() const; - uint16 getMeritModID() const; - ACTIONTYPE getActionType(); - EFFECT getPostActionEffectCleanup(); + uint16 getID() const; + uint16 getMobSkillID() const; + JOBTYPE getJob(); + uint8 getLevel() const; + uint16 getAnimationID() const; + timer::duration getAnimationTime(); + timer::duration getCastTime(); + float getRange() const; + uint8 getAOE() const; + uint16 getValidTarget() const; + uint16 getAddType() const; + uint16 getMessage() const; + uint16 getAoEMsg() const; + timer::duration getRecastTime() const; + uint16 getRecastId() const; + int32 getCE() const; + int32 getVE() const; + uint16 getMeritModID() const; + ACTIONTYPE getActionType(); + EFFECT getPostActionEffectCleanup(); void setID(uint16 id); void setMobSkillID(uint16 id); void setJob(JOBTYPE Job); void setLevel(uint8 level); void setAnimationID(uint16 animationID); - void setAnimationTime(duration time); - void setCastTime(duration time); + void setAnimationTime(timer::duration time); + void setCastTime(timer::duration time); void setRange(float range); void setAOE(uint8 aoe); void setValidTarget(uint16 validTarget); void setAddType(uint16 addtype); void setMessage(uint16 message); - void setRecastTime(uint16 recastTime); + void setRecastTime(timer::duration recastTime); void setRecastId(uint16 recastId); void setCE(int32 CE); void setVE(int32 VE); @@ -746,26 +746,26 @@ class CAbility void setName(const std::string& name); private: - uint16 m_ID; - JOBTYPE m_Job; - uint8 m_level; - uint16 m_animationID; - duration m_animationTime{}; - duration m_castTime{}; - float m_range; - uint8 m_aoe; - uint16 m_validTarget; - uint16 m_addType; - uint16 m_message; - uint16 m_recastTime; - uint16 m_recastId; - int32 m_CE; - int32 m_VE; - uint16 m_meritModID; - std::string m_name; - uint16 m_mobskillId; - ACTIONTYPE m_actionType{}; - EFFECT m_cleanupEffect{}; + uint16 m_ID; + JOBTYPE m_Job; + uint8 m_level; + uint16 m_animationID; + timer::duration m_animationTime{}; + timer::duration m_castTime{}; + float m_range; + uint8 m_aoe; + uint16 m_validTarget; + uint16 m_addType; + uint16 m_message; + timer::duration m_recastTime{}; + uint16 m_recastId; + int32 m_CE; + int32 m_VE; + uint16 m_meritModID; + std::string m_name; + uint16 m_mobskillId; + ACTIONTYPE m_actionType{}; + EFFECT m_cleanupEffect{}; }; /************************************************************************ diff --git a/src/map/ai/ai_container.cpp b/src/map/ai/ai_container.cpp index 184812e060b..1cbde9203f4 100644 --- a/src/map/ai/ai_container.cpp +++ b/src/map/ai/ai_container.cpp @@ -56,8 +56,8 @@ CAIContainer::CAIContainer(CBaseEntity* _PEntity, std::unique_ptr&& _ : TargetFind(std::move(_targetfind)) , PathFind(std::move(_pathfind)) , Controller(std::move(_controller)) -, m_Tick(server_clock::now()) -, m_PrevTick(server_clock::now()) +, m_Tick(timer::now()) +, m_PrevTick(timer::now()) , PEntity(_PEntity) , ActionQueue(_PEntity) { @@ -174,12 +174,12 @@ bool CAIContainer::UseItem(uint16 targid, uint8 loc, uint8 slotid) return false; } -bool CAIContainer::Inactive(duration _duration, bool canChangeState) +bool CAIContainer::Inactive(timer::duration _duration, bool canChangeState) { return ForceChangeState(PEntity, _duration, canChangeState, false); } -bool CAIContainer::Untargetable(duration _duration, bool canChangeState) +bool CAIContainer::Untargetable(timer::duration _duration, bool canChangeState) { return ForceChangeState(PEntity, _duration, canChangeState, true); } @@ -335,7 +335,7 @@ bool CAIContainer::Internal_RangedAttack(uint16 targetid) return false; } -bool CAIContainer::Internal_Die(duration deathTime) +bool CAIContainer::Internal_Die(timer::duration deathTime) { auto* entity = dynamic_cast(PEntity); if (entity) @@ -412,7 +412,7 @@ void CAIContainer::Reset() } } -void CAIContainer::Tick(time_point _tick) +void CAIContainer::Tick(timer::time_point _tick) { TracyZoneScoped; m_PrevTick = m_Tick; @@ -464,7 +464,7 @@ void CAIContainer::ClearStateStack() { while (!m_stateStack.empty()) { - m_stateStack.top()->Cleanup(server_clock::now()); + m_stateStack.top()->Cleanup(timer::now()); m_stateStack.pop(); } } @@ -473,7 +473,7 @@ void CAIContainer::InterruptStates() { while (!m_stateStack.empty() && m_stateStack.top()->CanInterrupt()) { - m_stateStack.top()->Cleanup(server_clock::now()); + m_stateStack.top()->Cleanup(timer::now()); m_stateStack.pop(); } } @@ -498,12 +498,12 @@ bool CAIContainer::IsUntargetable() return (PEntity->PAI->IsCurrentState() && static_cast(PEntity->PAI->GetCurrentState())->GetUntargetable()) || PEntity->GetUntargetable(); } -time_point CAIContainer::getTick() +timer::time_point CAIContainer::getTick() { return m_Tick; } -time_point CAIContainer::getPrevTick() +timer::time_point CAIContainer::getPrevTick() { return m_PrevTick; } @@ -542,7 +542,7 @@ void CAIContainer::ClearTimerQueue() void CAIContainer::checkQueueImmediately() { - ActionQueue.checkAction(server_clock::now()); + ActionQueue.checkAction(timer::now()); } bool CAIContainer::Internal_Despawn(bool instantDespawn) @@ -554,7 +554,7 @@ bool CAIContainer::Internal_Despawn(bool instantDespawn) return false; } -bool CAIContainer::Internal_Respawn(duration _duration) +bool CAIContainer::Internal_Respawn(timer::duration _duration) { if (!IsCurrentState()) { @@ -577,7 +577,7 @@ void CAIContainer::CheckCompletedStates() { while (!m_stateStack.empty() && m_stateStack.top()->IsCompleted()) { - m_stateStack.top()->Cleanup(server_clock::now()); + m_stateStack.top()->Cleanup(timer::now()); m_stateStack.pop(); } } diff --git a/src/map/ai/ai_container.h b/src/map/ai/ai_container.h index 5c2084adcbd..c9f0490d13d 100644 --- a/src/map/ai/ai_container.h +++ b/src/map/ai/ai_container.h @@ -61,8 +61,8 @@ class CAIContainer bool RangedAttack(uint16 targid); bool Trigger(CCharEntity* player); bool UseItem(uint16 targid, uint8 loc, uint8 slotid); - bool Inactive(duration _duration, bool canChangeState); - bool Untargetable(duration _duration, bool canChangeState); // Used to make owner entity untargetable & inactionable in TargetFind for _duration + bool Inactive(timer::duration _duration, bool canChangeState); + bool Untargetable(timer::duration _duration, bool canChangeState); // Used to make owner entity untargetable & inactionable in TargetFind for _duration /* Internal Controller functions */ bool Internal_Engage(uint16 targetid); @@ -74,15 +74,15 @@ class CAIContainer bool Internal_PetSkill(uint16 targid, uint16 abilityid); bool Internal_Ability(uint16 targetid, uint16 abilityid); bool Internal_RangedAttack(uint16 targetid); - bool Internal_Die(duration); + bool Internal_Die(timer::duration); bool Internal_Raise(); bool Internal_UseItem(uint16 targetid, uint8 loc, uint8 slotid); bool Internal_Despawn(bool instantDespawn = false); - bool Internal_Respawn(duration _duration); + bool Internal_Respawn(timer::duration _duration); bool Internal_Synth(SKILLTYPE synthSkill); void Reset(); - void Tick(time_point _tick); + void Tick(timer::time_point _tick); CState* GetCurrentState(); bool IsStateStackEmpty(); void ClearStateStack(); @@ -116,8 +116,8 @@ class CAIContainer void SetController(std::unique_ptr controller); CController* GetController(); - time_point getTick(); - time_point getPrevTick(); + timer::time_point getTick(); + timer::time_point getPrevTick(); void Despawn(); @@ -138,8 +138,8 @@ class CAIContainer // input controller std::unique_ptr Controller; // current synchronized server time (before AI loop execution) - time_point m_Tick; - time_point m_PrevTick; + timer::time_point m_Tick; + timer::time_point m_PrevTick; // entity who holds this AI CBaseEntity* PEntity; diff --git a/src/map/ai/controllers/automaton_controller.cpp b/src/map/ai/controllers/automaton_controller.cpp index 706710c9c82..2932e1ab7a0 100644 --- a/src/map/ai/controllers/automaton_controller.cpp +++ b/src/map/ai/controllers/automaton_controller.cpp @@ -175,7 +175,7 @@ CurrentManeuvers CAutomatonController::GetCurrentManeuvers() const statuses->GetEffectsCount(EFFECT_LIGHT_MANEUVER), statuses->GetEffectsCount(EFFECT_DARK_MANEUVER) }; } -void CAutomatonController::DoCombatTick(time_point tick) +void CAutomatonController::DoCombatTick(timer::time_point tick) { if ((PAutomaton->PMaster == nullptr || PAutomaton->PMaster->isDead()) && PAutomaton->isAlive()) { @@ -720,7 +720,7 @@ bool CAutomatonController::TryEnfeeble(const CurrentManeuvers& maneuvers) // clang-format off PTarget->StatusEffectContainer->ForEachEffect([&dispel](CStatusEffect* PStatus) { - if (!dispel && PStatus->GetDuration() > 0) + if (!dispel && PStatus->GetDuration() > 0s) { if (PStatus->HasEffectFlag(EFFECTFLAG_DISPELABLE)) { @@ -1083,7 +1083,7 @@ bool CAutomatonController::TryStatusRemoval(const CurrentManeuvers& maneuvers) // clang-format off PAutomaton->PMaster->StatusEffectContainer->ForEachEffect([&castPriority](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { auto id = automaton::FindNaSpell(PStatus); if (id.has_value()) @@ -1107,7 +1107,7 @@ bool CAutomatonController::TryStatusRemoval(const CurrentManeuvers& maneuvers) // clang-format off PAutomaton->StatusEffectContainer->ForEachEffect([&castPriority](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { auto id = automaton::FindNaSpell(PStatus); if (id.has_value()) @@ -1137,7 +1137,7 @@ bool CAutomatonController::TryStatusRemoval(const CurrentManeuvers& maneuvers) // clang-format off member->StatusEffectContainer->ForEachEffect([&castPriority](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { auto id = automaton::FindNaSpell(PStatus); if (id.has_value()) @@ -1217,7 +1217,7 @@ bool CAutomatonController::TryEnhance() PAutomaton->PMaster->StatusEffectContainer->ForEachEffect( [&protect, &protectcount, &shell, &shellcount, &haste, &stoneskin, &phalanx](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { if (PStatus->GetStatusID() == EFFECT_PROTECT) { @@ -1297,7 +1297,7 @@ bool CAutomatonController::TryEnhance() // clang-format off PAutomaton->StatusEffectContainer->ForEachEffect([&protect, &shell, &haste](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { if (PStatus->GetStatusID() == EFFECT_PROTECT) { @@ -1370,7 +1370,7 @@ bool CAutomatonController::TryEnhance() PMember->StatusEffectContainer->ForEachEffect([&protect, &protectcount, &shell, &shellcount, &haste](CStatusEffect* PStatus) { - if (PStatus->GetDuration() > 0) + if (PStatus->GetDuration() > 0s) { if (PStatus->GetStatusID() == EFFECT_PROTECT) { @@ -1515,7 +1515,7 @@ bool CAutomatonController::TryTPMove() if (attemptChain) { CStatusEffect* PSCEffect = PTarget->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN, 0); - if (PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now()) + if (PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now()) { std::list resonanceProperties; @@ -1577,8 +1577,8 @@ bool CAutomatonController::TryRangedAttack() // TODO: Find the animation for its { if (PAutomaton->getFrame() == FRAME_SHARPSHOT) { - duration minDelay = PAutomaton->getHead() == AUTOHEADTYPE::HEAD_SHARPSHOT ? 5s : 10s; - duration attackTime = m_rangedCooldown - std::chrono::seconds(PAutomaton->getMod(Mod::AUTO_RANGED_DELAY)); + timer::duration minDelay = PAutomaton->getHead() == AUTOHEADTYPE::HEAD_SHARPSHOT ? 5s : 10s; + timer::duration attackTime = m_rangedCooldown - std::chrono::seconds(PAutomaton->getMod(Mod::AUTO_RANGED_DELAY)); if (m_rangedCooldown > 0s && m_Tick > m_LastRangedTime + std::max(attackTime, minDelay)) { @@ -1615,7 +1615,7 @@ bool CAutomatonController::CanCastSpells() bool CAutomatonController::Cast(uint16 targid, SpellID spellid) { - if (!automaton::CanUseSpell(PAutomaton, spellid) || PAutomaton->PRecastContainer->HasRecast(RECAST_MAGIC, static_cast(spellid), 0)) + if (!automaton::CanUseSpell(PAutomaton, spellid) || PAutomaton->PRecastContainer->HasRecast(RECAST_MAGIC, static_cast(spellid), 0s)) { return false; } @@ -1625,7 +1625,7 @@ bool CAutomatonController::Cast(uint16 targid, SpellID spellid) bool CAutomatonController::MobSkill(uint16 targid, uint16 wsid) { - if (PAutomaton->PRecastContainer->HasRecast(RECAST_ABILITY, wsid, 0)) + if (PAutomaton->PRecastContainer->HasRecast(RECAST_ABILITY, wsid, 0s)) { return false; } diff --git a/src/map/ai/controllers/automaton_controller.h b/src/map/ai/controllers/automaton_controller.h index eb5924432a2..c121358376f 100644 --- a/src/map/ai/controllers/automaton_controller.h +++ b/src/map/ai/controllers/automaton_controller.h @@ -65,7 +65,7 @@ class CAutomatonController : public CPetController virtual bool Disengage() override; protected: - virtual void DoCombatTick(time_point tick) override; + virtual void DoCombatTick(timer::time_point tick) override; virtual void Move() override; void setCooldowns(); @@ -92,27 +92,27 @@ class CAutomatonController : public CPetController CAutomatonEntity* PAutomaton; - duration m_actionCooldown{ 3s }; - duration m_rangedCooldown{}; + timer::duration m_actionCooldown{ 3s }; + timer::duration m_rangedCooldown{}; static constexpr int m_RangedAbility{ 1949 }; - duration m_magicCooldown{}; - duration m_enfeebleCooldown{}; - duration m_elementalCooldown{}; - duration m_healCooldown{}; - duration m_enhanceCooldown{}; - duration m_statusCooldown{}; - duration m_shieldbashCooldown{}; + timer::duration m_magicCooldown{}; + timer::duration m_enfeebleCooldown{}; + timer::duration m_elementalCooldown{}; + timer::duration m_healCooldown{}; + timer::duration m_enhanceCooldown{}; + timer::duration m_statusCooldown{}; + timer::duration m_shieldbashCooldown{}; static constexpr int m_ShieldBashAbility{ 1944 }; - time_point m_LastActionTime; - time_point m_LastMagicTime; - time_point m_LastEnfeebleTime; - time_point m_LastElementalTime; - time_point m_LastHealTime; - time_point m_LastEnhanceTime; - time_point m_LastStatusTime; - time_point m_LastRangedTime; - time_point m_LastShieldBashTime; + timer::time_point m_LastActionTime; + timer::time_point m_LastMagicTime; + timer::time_point m_LastEnfeebleTime; + timer::time_point m_LastElementalTime; + timer::time_point m_LastHealTime; + timer::time_point m_LastEnhanceTime; + timer::time_point m_LastStatusTime; + timer::time_point m_LastRangedTime; + timer::time_point m_LastShieldBashTime; }; namespace automaton diff --git a/src/map/ai/controllers/controller.cpp b/src/map/ai/controllers/controller.cpp index 6942b176bed..0ac7b947eea 100644 --- a/src/map/ai/controllers/controller.cpp +++ b/src/map/ai/controllers/controller.cpp @@ -25,7 +25,7 @@ #include "entities/battleentity.h" CController::CController(CBattleEntity* _POwner) -: m_Tick(server_clock::now()) +: m_Tick(timer::now()) , POwner(_POwner) { } diff --git a/src/map/ai/controllers/controller.h b/src/map/ai/controllers/controller.h index 0974ea7d306..33bfef208a4 100644 --- a/src/map/ai/controllers/controller.h +++ b/src/map/ai/controllers/controller.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" +#include "common/timer.h" #include "spell.h" class CBattleEntity; @@ -35,7 +36,7 @@ class CController virtual ~CController() { } - virtual void Tick(time_point tick) = 0; + virtual void Tick(timer::time_point tick) = 0; virtual void Despawn(); virtual void Reset(); virtual bool Cast(uint16 targid, SpellID spellid); @@ -58,11 +59,11 @@ class CController bool canUpdate{ true }; protected: - time_point m_Tick; - CBattleEntity* POwner; - bool m_AutoAttackEnabled{ true }; - bool m_WeaponSkillEnabled{ true }; - bool m_MagicCastingEnabled{ true }; + timer::time_point m_Tick; + CBattleEntity* POwner; + bool m_AutoAttackEnabled{ true }; + bool m_WeaponSkillEnabled{ true }; + bool m_MagicCastingEnabled{ true }; }; #endif diff --git a/src/map/ai/controllers/mob_controller.cpp b/src/map/ai/controllers/mob_controller.cpp index ffb3daa0bb7..c18708b8599 100644 --- a/src/map/ai/controllers/mob_controller.cpp +++ b/src/map/ai/controllers/mob_controller.cpp @@ -45,7 +45,7 @@ CMobController::CMobController(CMobEntity* PEntity) { } -void CMobController::Tick(time_point tick) +void CMobController::Tick(timer::time_point tick) { TracyZoneScoped; TracyZoneString(PMob->getName()); @@ -563,7 +563,7 @@ void CMobController::CastSpell(SpellID spellid) } } -void CMobController::DoCombatTick(time_point tick) +void CMobController::DoCombatTick(timer::time_point tick) { TracyZoneScopedC(0xFF0000); if (PMob->m_OwnerID.targid != 0 && static_cast(PMob->GetEntity(PMob->m_OwnerID.targid))->PClaimedMob != static_cast(PMob)) @@ -886,7 +886,7 @@ void CMobController::HandleEnmity() } } -void CMobController::DoRoamTick(time_point tick) +void CMobController::DoRoamTick(timer::time_point tick) { TracyZoneScopedC(0x00FF00); // If there's someone on our enmity list, go from roaming -> engaging @@ -908,7 +908,7 @@ void CMobController::DoRoamTick(time_point tick) return; } // TODO - else if (PMob->GetDespawnTime() > time_point::min() && PMob->GetDespawnTime() < m_Tick) + else if (PMob->GetDespawnTime() > timer::time_point::min() && PMob->GetDespawnTime() < m_Tick) { Despawn(); return; @@ -1071,7 +1071,7 @@ void CMobController::DoRoamTick(time_point tick) } } -void CMobController::Wait(duration _duration) +void CMobController::Wait(timer::duration _duration) { if (m_Tick > m_WaitTime) { diff --git a/src/map/ai/controllers/mob_controller.h b/src/map/ai/controllers/mob_controller.h index fb25e6ddbf5..817c35f85f8 100644 --- a/src/map/ai/controllers/mob_controller.h +++ b/src/map/ai/controllers/mob_controller.h @@ -37,7 +37,7 @@ class CMobController : public CController public: CMobController(CMobEntity* PMob); - virtual void Tick(time_point tick) override; + virtual void Tick(timer::time_point tick) override; virtual bool Disengage() override; virtual bool Engage(uint16 targid) override; virtual void Despawn() override; @@ -76,12 +76,12 @@ class CMobController : public CController void CastSpell(SpellID spellid); virtual void Move(); - virtual void DoCombatTick(time_point tick); + virtual void DoCombatTick(timer::time_point tick); void FaceTarget(uint16 targid = 0); virtual void HandleEnmity(); - virtual void DoRoamTick(time_point tick); - void Wait(duration _duration); + virtual void DoRoamTick(timer::time_point tick); + void Wait(timer::duration _duration); void FollowRoamPath(); bool CanMoveForward(float currentDistance); bool IsSpecialSkillReady(float currentDistance); @@ -96,19 +96,19 @@ class CMobController : public CController private: CMobEntity* const PMob; - time_point m_LastActionTime; - time_point m_nextMagicTime; - time_point m_LastMobSkillTime; - time_point m_LastSpecialTime; - time_point m_DeaggroTime; - time_point m_DeclaimTime; - time_point m_NeutralTime; - time_point m_WaitTime; - time_point m_mobHealTime; - FollowType m_followType = FollowType::None; - - bool m_firstSpell{ true }; - time_point m_LastRoamScript{ time_point::min() }; + timer::time_point m_LastActionTime; + timer::time_point m_nextMagicTime; + timer::time_point m_LastMobSkillTime; + timer::time_point m_LastSpecialTime; + timer::time_point m_DeaggroTime; + timer::time_point m_DeclaimTime; + timer::time_point m_NeutralTime; + timer::time_point m_WaitTime; + timer::time_point m_mobHealTime; + FollowType m_followType = FollowType::None; + + bool m_firstSpell{ true }; + timer::time_point m_LastRoamScript{ timer::time_point::min() }; }; #endif // _AI_CONTROLLER_H diff --git a/src/map/ai/controllers/pet_controller.cpp b/src/map/ai/controllers/pet_controller.cpp index 65a86c003ae..600df3f6eac 100644 --- a/src/map/ai/controllers/pet_controller.cpp +++ b/src/map/ai/controllers/pet_controller.cpp @@ -35,7 +35,7 @@ CPetController::CPetController(CMobEntity* _PPet) SetWeaponSkillEnabled(false); } -void CPetController::Tick(time_point tick) +void CPetController::Tick(timer::time_point tick) { TracyZoneScoped; TracyZoneString(PPet->getName()); @@ -56,9 +56,7 @@ void CPetController::Tick(time_point tick) auto* PPetEntity = dynamic_cast(PPet); if (PPetEntity && PPetEntity->isAlive() && PPetEntity->getPetType() == PET_TYPE::JUG_PET) { - // need to covert tick to unix time (in seconds) because getJugSpawnTime and getJugDuration give unix time - auto tickAsUnixTime = static_cast(std::chrono::duration_cast(tick.time_since_epoch()).count()); - if (tickAsUnixTime > PPetEntity->getJugSpawnTime() + PPetEntity->getJugDuration()) + if (tick > PPetEntity->getJugSpawnTime() + PPetEntity->getJugDuration()) { petutils::DespawnPet(PPetEntity->PMaster); return; @@ -68,7 +66,7 @@ void CPetController::Tick(time_point tick) CMobController::Tick(tick); } -void CPetController::DoRoamTick(time_point tick) +void CPetController::DoRoamTick(timer::time_point tick) { if ((PPet->PMaster == nullptr || PPet->PMaster->isDead()) && PPet->isAlive() && PPet->objtype != TYPE_MOB) { @@ -143,7 +141,7 @@ bool CPetController::PetIsHealing() { // animation down PPet->animation = ANIMATION_HEALING; - PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, settings::get("map.HEALING_TICK_DELAY"), 0)); + PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, std::chrono::seconds(settings::get("map.HEALING_TICK_DELAY")), 0s)); PPet->updatemask |= UPDATE_HP; return true; } diff --git a/src/map/ai/controllers/pet_controller.h b/src/map/ai/controllers/pet_controller.h index 0df136730dc..837e296fbbd 100644 --- a/src/map/ai/controllers/pet_controller.h +++ b/src/map/ai/controllers/pet_controller.h @@ -31,13 +31,13 @@ class CPetController : public CMobController CPetController(CMobEntity* PPet); static constexpr float PetRoamDistance{ 2.1f }; - virtual void DoRoamTick(time_point tick) override; + virtual void DoRoamTick(timer::time_point tick) override; bool PetSkill(uint16 targid, uint16 abilityid); protected: bool PetIsHealing(); - virtual void Tick(time_point tick) override; + virtual void Tick(timer::time_point tick) override; virtual void HandleEnmity() override { } diff --git a/src/map/ai/controllers/player_charm_controller.cpp b/src/map/ai/controllers/player_charm_controller.cpp index bd6ceadc13e..63eeafd6ed4 100644 --- a/src/map/ai/controllers/player_charm_controller.cpp +++ b/src/map/ai/controllers/player_charm_controller.cpp @@ -42,7 +42,7 @@ CPlayerCharmController::~CPlayerCharmController() POwner->allegiance = ALLEGIANCE_TYPE::PLAYER; } -void CPlayerCharmController::Tick(time_point tick) +void CPlayerCharmController::Tick(timer::time_point tick) { m_Tick = tick; if (POwner->PMaster == nullptr || !POwner->PMaster->isAlive()) @@ -61,7 +61,7 @@ void CPlayerCharmController::Tick(time_point tick) } } -void CPlayerCharmController::DoCombatTick(time_point tick) +void CPlayerCharmController::DoCombatTick(timer::time_point tick) { if (!POwner->PMaster->PAI->IsEngaged()) { @@ -90,7 +90,7 @@ void CPlayerCharmController::DoCombatTick(time_point tick) } } -void CPlayerCharmController::DoRoamTick(time_point tick) +void CPlayerCharmController::DoRoamTick(timer::time_point tick) { if (POwner->PMaster->PAI->IsEngaged()) { diff --git a/src/map/ai/controllers/player_charm_controller.h b/src/map/ai/controllers/player_charm_controller.h index bae8e9a30ea..0985c9e8a93 100644 --- a/src/map/ai/controllers/player_charm_controller.h +++ b/src/map/ai/controllers/player_charm_controller.h @@ -32,7 +32,7 @@ class CPlayerCharmController : public CPlayerController CPlayerCharmController(CCharEntity*); virtual ~CPlayerCharmController(); - virtual void Tick(time_point) override; + virtual void Tick(timer::time_point) override; virtual bool Cast(uint16 targid, SpellID spellid) override { @@ -58,8 +58,8 @@ class CPlayerCharmController : public CPlayerController private: static constexpr float RoamDistance{ 2.1f }; - void DoCombatTick(time_point tick); - void DoRoamTick(time_point tick); + void DoCombatTick(timer::time_point tick); + void DoRoamTick(timer::time_point tick); }; #endif // _PLAYERCONTROLLER diff --git a/src/map/ai/controllers/player_controller.cpp b/src/map/ai/controllers/player_controller.cpp index 53c94f3992d..d2780cf7f54 100644 --- a/src/map/ai/controllers/player_controller.cpp +++ b/src/map/ai/controllers/player_controller.cpp @@ -41,14 +41,14 @@ CPlayerController::CPlayerController(CCharEntity* _PChar) { } -void CPlayerController::Tick(time_point /*tick*/) +void CPlayerController::Tick(timer::time_point /*tick*/) { } bool CPlayerController::Cast(uint16 targid, SpellID spellid) { auto* PChar = static_cast(POwner); - if (!PChar->PRecastContainer->HasRecast(RECAST_MAGIC, static_cast(spellid), 0)) + if (!PChar->PRecastContainer->HasRecast(RECAST_MAGIC, static_cast(spellid), 0s)) { if (auto target = PChar->GetEntity(targid); target && target->PAI->IsUntargetable()) { @@ -74,7 +74,7 @@ bool CPlayerController::Engage(uint16 targid) { if (distance(PChar->loc.p, PTarget->loc.p) < 30) { - if (m_lastAttackTime + std::chrono::milliseconds(PChar->GetWeaponDelay(false)) < server_clock::now()) + if (m_lastAttackTime + std::chrono::milliseconds(PChar->GetWeaponDelay(false)) < timer::now()) { if (CController::Engage(targid)) { @@ -124,17 +124,17 @@ bool CPlayerController::Ability(uint16 targid, uint16 abilityid) if (PChar->PRecastContainer->HasRecast(RECAST_ABILITY, PAbility->getRecastId(), PAbility->getRecastTime())) { Recast_t* recast = PChar->PRecastContainer->GetRecast(RECAST_ABILITY, PAbility->getRecastId()); - // Set recast time in seconds to the normal recast time minus any charge time with the difference of the current time minus when the recast was set. + // Set recast time to the normal recast time minus any charge time. // Abilities without a charge will have zero chargeTime - uint32 recastSeconds = recast->RecastTime - ((uint32)time(nullptr) - recast->TimeStamp); + timer::duration currentRecast = recast->TimeStamp - timer::now() + recast->RecastTime; // Abilities with a single charge (low-level scholoar stratagems) behave like abilities without a charge if (recast->maxCharges > 1) { - recastSeconds -= (recast->maxCharges - 1) * recast->chargeTime; + currentRecast -= recast->chargeTime * (recast->maxCharges - 1); } PChar->pushPacket(PChar, PChar, 0, 0, MSGBASIC_UNABLE_TO_USE_JA2); - PChar->pushPacket(PChar, PChar, recastSeconds, 0, MSGBASIC_TIME_LEFT); + PChar->pushPacket(PChar, PChar, timer::count_seconds(currentRecast), 0, MSGBASIC_TIME_LEFT); return false; } if (auto target = PChar->GetEntity(targid); target && target->PAI->IsUntargetable()) @@ -260,22 +260,22 @@ bool CPlayerController::WeaponSkill(uint16 targid, uint16 wsid) return false; } -time_point CPlayerController::getLastAttackTime() +timer::time_point CPlayerController::getLastAttackTime() { return m_lastAttackTime; } -void CPlayerController::setLastAttackTime(time_point _lastAttackTime) +void CPlayerController::setLastAttackTime(timer::time_point _lastAttackTime) { m_lastAttackTime = _lastAttackTime; } -void CPlayerController::setLastErrMsgTime(time_point _LastErrMsgTime) +void CPlayerController::setLastErrMsgTime(timer::time_point _LastErrMsgTime) { m_errMsgTime = _LastErrMsgTime; } -time_point CPlayerController::getLastErrMsgTime() +timer::time_point CPlayerController::getLastErrMsgTime() { return m_errMsgTime; } diff --git a/src/map/ai/controllers/player_controller.h b/src/map/ai/controllers/player_controller.h index 85cd11bb911..34873a09905 100644 --- a/src/map/ai/controllers/player_controller.h +++ b/src/map/ai/controllers/player_controller.h @@ -35,7 +35,7 @@ class CPlayerController : public CController { } - virtual void Tick(time_point) override; + virtual void Tick(timer::time_point) override; virtual bool Cast(uint16 targid, SpellID spellid) override; virtual bool Engage(uint16 targid) override; @@ -47,18 +47,18 @@ class CPlayerController : public CController virtual bool RangedAttack(uint16 targid); virtual bool UseItem(uint16 targid, uint8 loc, uint8 slotid); - time_point getLastAttackTime(); - void setLastAttackTime(time_point); + timer::time_point getLastAttackTime(); + void setLastAttackTime(timer::time_point); - void setLastErrMsgTime(time_point); - time_point getLastErrMsgTime(); + void setLastErrMsgTime(timer::time_point); + timer::time_point getLastErrMsgTime(); CWeaponSkill* getLastWeaponSkill(); protected: - time_point m_lastAttackTime{ server_clock::now() }; - time_point m_errMsgTime{ server_clock::now() }; - CWeaponSkill* m_lastWeaponSkill{ nullptr }; + timer::time_point m_lastAttackTime{ timer::now() }; + timer::time_point m_errMsgTime{ timer::now() }; + CWeaponSkill* m_lastWeaponSkill{ nullptr }; }; #endif // _PLAYERCONTROLLER diff --git a/src/map/ai/controllers/trust_controller.cpp b/src/map/ai/controllers/trust_controller.cpp index 14e6859e753..75ad7238fc3 100644 --- a/src/map/ai/controllers/trust_controller.cpp +++ b/src/map/ai/controllers/trust_controller.cpp @@ -83,7 +83,7 @@ void CTrustController::Despawn() CMobController::Despawn(); } -void CTrustController::Tick(time_point tick) +void CTrustController::Tick(timer::time_point tick) { TracyZoneScoped; TracyZoneString(POwner->getName()); @@ -110,7 +110,7 @@ void CTrustController::Tick(time_point tick) } } -void CTrustController::DoCombatTick(time_point tick) +void CTrustController::DoCombatTick(timer::time_point tick) { TracyZoneScoped; @@ -215,13 +215,13 @@ void CTrustController::DoCombatTick(time_point tick) } } -void CTrustController::DoRoamTick(time_point tick) +void CTrustController::DoRoamTick(timer::time_point tick) { TracyZoneScoped; auto* PMaster = static_cast(POwner->PMaster); auto masterLastAttackTime = static_cast(PMaster->PAI->GetController())->getLastAttackTime(); - bool masterMeleeSwing = masterLastAttackTime > server_clock::now() - 1s; + bool masterMeleeSwing = masterLastAttackTime > timer::now() - 1s; bool trustEngageCondition = false; // NOTE: charvars are now cached, this is essentially a localvar read now. @@ -407,7 +407,7 @@ bool CTrustController::Ability(uint16 targid, uint16 abilityid) { TracyZoneScoped; - if (static_cast(POwner)->PRecastContainer->HasRecast(RECAST_ABILITY, abilityid, 0)) + if (static_cast(POwner)->PRecastContainer->HasRecast(RECAST_ABILITY, abilityid, 0s)) { return false; } @@ -424,7 +424,7 @@ bool CTrustController::RangedAttack(uint16 targid) { TracyZoneScoped; - duration rangedDelay = 10s; + timer::duration rangedDelay = 10s; if (CItemWeapon* PRange = dynamic_cast(POwner->m_Weapons[SLOT_RANGED])) { rangedDelay = std::chrono::milliseconds(PRange->getDelay()); diff --git a/src/map/ai/controllers/trust_controller.h b/src/map/ai/controllers/trust_controller.h index cc5b9e5ab9c..cb410a8b2c9 100644 --- a/src/map/ai/controllers/trust_controller.h +++ b/src/map/ai/controllers/trust_controller.h @@ -40,7 +40,7 @@ class CTrustController : public CMobController CTrustController(CCharEntity*, CTrustEntity*); ~CTrustController() override; - void Tick(time_point) override; + void Tick(timer::time_point) override; void Despawn() override; bool Ability(uint16 targid, uint16 abilityid) override; @@ -60,24 +60,24 @@ class CTrustController : public CMobController std::unique_ptr m_GambitsContainer; private: - void DoCombatTick(time_point tick) override; - void DoRoamTick(time_point tick) override; + void DoCombatTick(timer::time_point tick) override; + void DoRoamTick(timer::time_point tick) override; void Declump(CCharEntity* PMaster, CBattleEntity* PTarget); void PathOutToDistance(CBattleEntity* PTarget, float amount); CBattleEntity* m_LastTopEnmity; - time_point m_LastRepositionTime; - uint8 m_failedRepositionAttempts; - bool m_InTransit; + timer::time_point m_LastRepositionTime; + uint8 m_failedRepositionAttempts; + bool m_InTransit; - time_point m_CombatEndTime; - time_point m_LastHealTickTime; + timer::time_point m_CombatEndTime; + timer::time_point m_LastHealTickTime; std::vector m_tickDelays = { 15s, 10s, 10s, 3s }; std::size_t m_NumHealingTicks = { 0 }; - time_point m_LastRangedAttackTime; + timer::time_point m_LastRangedAttackTime; }; #endif // _TRUSTCONTROLLER diff --git a/src/map/ai/helpers/action_queue.cpp b/src/map/ai/helpers/action_queue.cpp index 91c82dddf55..6514329ebeb 100644 --- a/src/map/ai/helpers/action_queue.cpp +++ b/src/map/ai/helpers/action_queue.cpp @@ -42,7 +42,7 @@ void CAIActionQueue::pushAction(queueAction_t&& action) } } -void CAIActionQueue::checkAction(time_point tick) +void CAIActionQueue::checkAction(timer::time_point tick) { while (!timerQueue.empty()) { diff --git a/src/map/ai/helpers/action_queue.h b/src/map/ai/helpers/action_queue.h index f9a62e881af..4b6f27eb130 100644 --- a/src/map/ai/helpers/action_queue.h +++ b/src/map/ai/helpers/action_queue.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" +#include "common/timer.h" #include #include #include @@ -36,11 +37,11 @@ struct queueAction_t { using EntityFunc_t = std::function; - time_point start_time{ server_clock::now() }; - duration delay{ 0ms }; - bool checkState{ false }; - sol::function lua_func{}; - EntityFunc_t func{}; + timer::time_point start_time{ timer::now() }; + timer::duration delay{ 0ms }; + bool checkState{ false }; + sol::function lua_func{}; + EntityFunc_t func{}; queueAction_t(int _ms, bool _checkstate, sol::function _lua_func) : delay(std::chrono::milliseconds(_ms)) @@ -49,7 +50,7 @@ struct queueAction_t { } - queueAction_t(duration _ms, bool _checkstate, std::function _func) + queueAction_t(timer::duration _ms, bool _checkstate, std::function _func) : delay(_ms) , checkState(_checkstate) , func(_func) @@ -80,7 +81,7 @@ class CAIActionQueue CAIActionQueue(CBaseEntity*); void pushAction(queueAction_t&&); - void checkAction(time_point tick); + void checkAction(timer::time_point tick); void handleAction(queueAction_t& action); diff --git a/src/map/ai/helpers/gambits_container.cpp b/src/map/ai/helpers/gambits_container.cpp index 0b81ecc14e0..de07447e5e5 100644 --- a/src/map/ai/helpers/gambits_container.cpp +++ b/src/map/ai/helpers/gambits_container.cpp @@ -86,7 +86,7 @@ namespace gambits gambits.clear(); } - void CGambitsContainer::Tick(time_point tick) + void CGambitsContainer::Tick(timer::time_point tick) { TracyZoneScoped; @@ -736,7 +736,7 @@ namespace gambits case G_CONDITION::SC_AVAILABLE: { auto* PSCEffect = triggerTarget->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN); - predicateResults.push_back(PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now() && PSCEffect->GetTier() == 0); + predicateResults.push_back(PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now() && PSCEffect->GetTier() == 0); continue; } case G_CONDITION::NOT_SC_AVAILABLE: @@ -748,7 +748,7 @@ namespace gambits case G_CONDITION::MB_AVAILABLE: { auto* PSCEffect = triggerTarget->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN); - predicateResults.push_back(PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now() && PSCEffect->GetTier() > 0); + predicateResults.push_back(PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now() && PSCEffect->GetTier() > 0); continue; } case G_CONDITION::READYING_WS: @@ -852,7 +852,7 @@ namespace gambits // TODO: ...and has a valid WS... - return PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now() && PSCEffect->GetTier() == 0; + return PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now() && PSCEffect->GetTier() == 0; break; } case G_TP_TRIGGER::CLOSER_UNTIL_TP: // Will hold TP to close a SC, but WS immediately once specified value is reached. @@ -869,7 +869,7 @@ namespace gambits // TODO: ...and has a valid WS... - return PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now() && PSCEffect->GetTier() == 0; + return PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now() && PSCEffect->GetTier() == 0; break; } default: diff --git a/src/map/ai/helpers/gambits_container.h b/src/map/ai/helpers/gambits_container.h index 2b508401776..029dce1668f 100644 --- a/src/map/ai/helpers/gambits_container.h +++ b/src/map/ai/helpers/gambits_container.h @@ -214,7 +214,7 @@ namespace gambits std::vector actions; G_TARGET target_selector; uint16 retry_delay; - time_point last_used; + timer::time_point last_used; std::string identifier; Gambit_t() @@ -275,7 +275,7 @@ namespace gambits auto AddGambit(Gambit_t const& gambit) -> std::string; void RemoveGambit(std::string const& id); void RemoveAllGambits(); - void Tick(time_point tick); + void Tick(timer::time_point tick); // TODO: make private std::vector tp_skills; @@ -290,7 +290,7 @@ namespace gambits bool PartyHasTank(); CTrustEntity* POwner; - time_point m_lastAction; + timer::time_point m_lastAction; std::vector gambits; // clang-format off diff --git a/src/map/ai/helpers/pathfind.cpp b/src/map/ai/helpers/pathfind.cpp index 5c028762b07..3426af2e232 100644 --- a/src/map/ai/helpers/pathfind.cpp +++ b/src/map/ai/helpers/pathfind.cpp @@ -99,7 +99,7 @@ bool CPathFind::RoamAround(const position_t& point, float maxRadius, uint8 maxTu return false; } - m_points.emplace_back(pathpoint_t{ { point.x - 1 + rand() % 2, point.y, point.z - 1 + rand() % 2, 0, 0 }, 0, false }); + m_points.emplace_back(pathpoint_t{ { point.x - 1 + rand() % 2, point.y, point.z - 1 + rand() % 2, 0, 0 }, 0s, false }); } return true; @@ -148,7 +148,7 @@ bool CPathFind::PathTo(const position_t& point, uint8 pathFlags, bool clear) Clear(); } - m_points.emplace_back(pathpoint_t{ point, 0, false }); + m_points.emplace_back(pathpoint_t{ point, 0s, false }); } return true; @@ -280,7 +280,7 @@ void CPathFind::PrunePathWithin(float within) } } -void CPathFind::FollowPath(time_point tick) +void CPathFind::FollowPath(timer::time_point tick) { TracyZoneScoped; if (!IsFollowingPath()) @@ -288,12 +288,12 @@ void CPathFind::FollowPath(time_point tick) return; } - if (m_timeAtPoint.time_since_epoch().count() != 0) + if (m_timeAtPoint != timer::time_point::min()) { // Continue to wait until full wait time has elapsed if (tick >= m_timeAtPoint) { - m_timeAtPoint = {}; + m_timeAtPoint = timer::time_point::min(); ++m_currentPoint; luautils::OnPathPoint(m_POwner); if (m_currentPoint >= (int16)m_points.size()) @@ -336,9 +336,9 @@ void CPathFind::FollowPath(time_point tick) m_POwner->loc.p.rotation = targetPoint.position.rotation; m_POwner->updatemask |= UPDATE_POS; } - if (targetPoint.wait != 0 && m_timeAtPoint.time_since_epoch().count() == 0) + if (targetPoint.wait != 0s && m_timeAtPoint == timer::time_point::min()) { - m_timeAtPoint = tick + std::chrono::milliseconds(targetPoint.wait); + m_timeAtPoint = tick + targetPoint.wait; return; } @@ -538,7 +538,7 @@ bool CPathFind::FindClosestPath(const position_t& start, const position_t& end) m_points = m_POwner->loc.zone->m_navMesh->findPath(start, end); m_currentPoint = 0; - m_points.emplace_back(pathpoint_t{ end, 0, false }); // this prevents exploits with navmesh / impassible terrain + m_points.emplace_back(pathpoint_t{ end, 0s, false }); // this prevents exploits with navmesh / impassible terrain /* this check requirement is never met as intended since m_points are never empty when mob has a path if (m_points.empty()) @@ -619,7 +619,7 @@ void CPathFind::Clear() m_pathFlags = 0; m_roamFlags = 0; m_points.clear(); - m_timeAtPoint = {}; + m_timeAtPoint = timer::time_point::min(); m_currentPoint = 0; m_maxDistance = 0; diff --git a/src/map/ai/helpers/pathfind.h b/src/map/ai/helpers/pathfind.h index 3bddea97be8..7b848944326 100644 --- a/src/map/ai/helpers/pathfind.h +++ b/src/map/ai/helpers/pathfind.h @@ -24,6 +24,7 @@ #include "common/logging.h" #include "common/mmo.h" +#include "common/timer.h" #include @@ -73,7 +74,7 @@ class CPathFind void ResumePatrol(); // moves mob to next point - void FollowPath(time_point tick); + void FollowPath(timer::time_point tick); // returns true if entity is on a way point bool OnPoint() const; @@ -146,7 +147,7 @@ class CPathFind bool m_onPoint; int16 m_currentPoint; - time_point m_timeAtPoint; + timer::time_point m_timeAtPoint; uint8 m_currentTurn; diff --git a/src/map/ai/states/ability_state.cpp b/src/map/ai/states/ability_state.cpp index af1e421458f..bb08fea0355 100644 --- a/src/map/ai/states/ability_state.cpp +++ b/src/map/ai/states/ability_state.cpp @@ -115,7 +115,7 @@ bool CAbilityState::CanChangeState() return IsCompleted(); } -bool CAbilityState::Update(time_point tick) +bool CAbilityState::Update(timer::time_point tick) { // Rotate towards target during ability if (m_castTime > 0s && tick < GetEntryTime() + m_castTime) diff --git a/src/map/ai/states/ability_state.h b/src/map/ai/states/ability_state.h index f658dd3be11..9f4aff9b372 100644 --- a/src/map/ai/states/ability_state.h +++ b/src/map/ai/states/ability_state.h @@ -46,15 +46,15 @@ class CAbilityState : public CState { return true; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override { } bool CanUseAbility(); private: - duration m_castTime{ 0s }; + timer::duration m_castTime{ 0s }; CBattleEntity* const m_PEntity; std::unique_ptr m_PAbility; }; diff --git a/src/map/ai/states/attack_state.cpp b/src/map/ai/states/attack_state.cpp index e970ec87dc0..fae77b67647 100644 --- a/src/map/ai/states/attack_state.cpp +++ b/src/map/ai/states/attack_state.cpp @@ -33,7 +33,7 @@ CAttackState::CAttackState(CBattleEntity* PEntity, uint16 targid) , m_PEntity(PEntity) { PEntity->SetBattleTargetID(targid); - PEntity->SetBattleStartTime(server_clock::now()); + PEntity->SetBattleStartTime(timer::now()); CAttackState::UpdateTarget(); if (!GetTarget() || m_errorMsg) @@ -55,7 +55,7 @@ CAttackState::CAttackState(CBattleEntity* PEntity, uint16 targid) } } -bool CAttackState::Update(time_point tick) +bool CAttackState::Update(timer::time_point tick) { auto* PTarget = static_cast(GetTarget()); if (!PTarget || PTarget->isDead()) @@ -97,7 +97,7 @@ bool CAttackState::Update(time_point tick) return false; } -void CAttackState::Cleanup(time_point tick) +void CAttackState::Cleanup(timer::time_point tick) { if (!m_PEntity->isDead()) { diff --git a/src/map/ai/states/attack_state.h b/src/map/ai/states/attack_state.h index 8696afbf93a..c48e911d52f 100644 --- a/src/map/ai/states/attack_state.h +++ b/src/map/ai/states/attack_state.h @@ -30,9 +30,9 @@ class CAttackState : public CState CAttackState(CBattleEntity* PEntity, uint16 targid); // state logic done per tick - returns whether to exit the state or not - virtual bool Update(time_point tick) override; + virtual bool Update(timer::time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; // whether the state can be changed by normal means virtual bool CanChangeState() override { @@ -58,7 +58,7 @@ class CAttackState : public CState private: CBattleEntity* const m_PEntity; - duration m_attackTime{ 2s }; + timer::duration m_attackTime{ 2s }; }; #endif diff --git a/src/map/ai/states/death_state.cpp b/src/map/ai/states/death_state.cpp index 008aed5c9d1..f986d96228c 100644 --- a/src/map/ai/states/death_state.cpp +++ b/src/map/ai/states/death_state.cpp @@ -30,10 +30,10 @@ namespace { - static const duration TIME_TO_SEND_RERAISE_MENU = 8s; + static const timer::duration TIME_TO_SEND_RERAISE_MENU = 8s; } -CDeathState::CDeathState(CBattleEntity* PEntity, duration death_time) +CDeathState::CDeathState(CBattleEntity* PEntity, timer::duration death_time) : CState(PEntity, PEntity->targid) , m_PEntity(PEntity) , m_deathTime(death_time) @@ -49,7 +49,7 @@ CDeathState::CDeathState(CBattleEntity* PEntity, duration death_time) } } -bool CDeathState::Update(time_point tick) +bool CDeathState::Update(timer::time_point tick) { // It's completed if (IsCompleted() || m_PEntity->animation != ANIMATION_DEATH) @@ -82,6 +82,6 @@ bool CDeathState::Update(time_point tick) void CDeathState::allowSendRaise() { - m_raiseTime = server_clock::now() + 12s; + m_raiseTime = timer::now() + 12s; m_raiseSent = false; } diff --git a/src/map/ai/states/death_state.h b/src/map/ai/states/death_state.h index 918293d113a..f70889ce24d 100644 --- a/src/map/ai/states/death_state.h +++ b/src/map/ai/states/death_state.h @@ -27,12 +27,12 @@ class CDeathState : public CState { public: - CDeathState(CBattleEntity* PEntity, duration death_time); + CDeathState(CBattleEntity* PEntity, timer::duration death_time); // state logic done per tick - returns whether to exit the state or not - virtual bool Update(time_point tick) override; + virtual bool Update(timer::time_point tick) override; - virtual void Cleanup(time_point tick) override + virtual void Cleanup(timer::time_point tick) override { } // whether the state can be changed by normal means @@ -53,9 +53,9 @@ class CDeathState : public CState private: CBattleEntity* const m_PEntity; - duration m_deathTime; + timer::duration m_deathTime; bool m_raiseSent{ false }; - time_point m_raiseTime; + timer::time_point m_raiseTime; }; #endif diff --git a/src/map/ai/states/despawn_state.cpp b/src/map/ai/states/despawn_state.cpp index d1b0aae8ec2..df6d79806ff 100644 --- a/src/map/ai/states/despawn_state.cpp +++ b/src/map/ai/states/despawn_state.cpp @@ -35,7 +35,7 @@ CDespawnState::CDespawnState(CBaseEntity* _PEntity, bool instantDespawn) } } -bool CDespawnState::Update(time_point tick) +bool CDespawnState::Update(timer::time_point tick) { if (tick > GetEntryTime() + 3s && !IsCompleted() && !(static_cast(m_PEntity)->m_Behavior & BEHAVIOR_NO_DESPAWN)) { @@ -45,7 +45,7 @@ bool CDespawnState::Update(time_point tick) return IsCompleted(); } -void CDespawnState::Cleanup(time_point tick) +void CDespawnState::Cleanup(timer::time_point tick) { } diff --git a/src/map/ai/states/despawn_state.h b/src/map/ai/states/despawn_state.h index a2d1dbeb5af..cc348eece27 100644 --- a/src/map/ai/states/despawn_state.h +++ b/src/map/ai/states/despawn_state.h @@ -28,8 +28,8 @@ class CDespawnState : public CState { public: CDespawnState(CBaseEntity* PEntity, bool instantDespawn); - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; virtual bool CanChangeState() override; virtual bool CanFollowPath() override { diff --git a/src/map/ai/states/inactive_state.cpp b/src/map/ai/states/inactive_state.cpp index 8add9dcf9e3..e25432b6ba8 100644 --- a/src/map/ai/states/inactive_state.cpp +++ b/src/map/ai/states/inactive_state.cpp @@ -24,7 +24,7 @@ #include "entities/battleentity.h" #include "status_effect_container.h" -CInactiveState::CInactiveState(CBaseEntity* PEntity, duration _duration, bool canChangeState, bool untargetable) +CInactiveState::CInactiveState(CBaseEntity* PEntity, timer::duration _duration, bool canChangeState, bool untargetable) : CState(PEntity, 0) , m_duration(_duration) , m_canChangeState(canChangeState) @@ -36,7 +36,7 @@ CInactiveState::CInactiveState(CBaseEntity* PEntity, duration _duration, bool ca } } -bool CInactiveState::Update(time_point tick) +bool CInactiveState::Update(timer::time_point tick) { auto* PBattleEntity{ dynamic_cast(m_PEntity) }; if (PBattleEntity && m_duration == 0ms) @@ -56,6 +56,6 @@ bool CInactiveState::Update(time_point tick) return m_duration > 0ms && tick > GetEntryTime() + m_duration; } -void CInactiveState::Cleanup(time_point tick) +void CInactiveState::Cleanup(timer::time_point tick) { } diff --git a/src/map/ai/states/inactive_state.h b/src/map/ai/states/inactive_state.h index 2e791dd1c58..44aa4e2736b 100644 --- a/src/map/ai/states/inactive_state.h +++ b/src/map/ai/states/inactive_state.h @@ -27,7 +27,7 @@ class CInactiveState : public CState { public: - CInactiveState(CBaseEntity* PEntity, duration _duration, bool canChangeState, bool untargetable); + CInactiveState(CBaseEntity* PEntity, timer::duration _duration, bool canChangeState, bool untargetable); bool GetUntargetable() { @@ -48,13 +48,13 @@ class CInactiveState : public CState return false; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; private: - duration m_duration; - bool m_canChangeState{ false }; - bool m_untargetable{ false }; + timer::duration m_duration; + bool m_canChangeState{ false }; + bool m_untargetable{ false }; }; #endif diff --git a/src/map/ai/states/item_state.cpp b/src/map/ai/states/item_state.cpp index c3c45dc6b71..4c8afa655dc 100644 --- a/src/map/ai/states/item_state.cpp +++ b/src/map/ai/states/item_state.cpp @@ -113,8 +113,8 @@ CItemState::CItemState(CCharEntity* PEntity, uint16 targid, uint8 loc, uint8 slo m_PEntity->UContainer->SetItem(0, m_PItem); m_startPos = m_PEntity->loc.p; - m_castTime = std::chrono::milliseconds(m_PItem->getActivationTime()); - m_animationTime = std::chrono::milliseconds(m_PItem->getAnimationTime()); + m_castTime = m_PItem->getActivationTime(); + m_animationTime = m_PItem->getAnimationTime(); action_t action; action.id = m_PEntity->id; @@ -171,7 +171,7 @@ void CItemState::UpdateTarget(uint16 targid) } } -bool CItemState::Update(time_point tick) +bool CItemState::Update(timer::time_point tick) { if (tick > GetEntryTime() + m_castTime && !IsCompleted()) { @@ -205,7 +205,7 @@ bool CItemState::Update(time_point tick) return false; } -void CItemState::Cleanup(time_point tick) +void CItemState::Cleanup(timer::time_point tick) { m_PEntity->UContainer->Clean(); diff --git a/src/map/ai/states/item_state.h b/src/map/ai/states/item_state.h index d545dc97c41..d2984b58c22 100644 --- a/src/map/ai/states/item_state.h +++ b/src/map/ai/states/item_state.h @@ -36,8 +36,8 @@ class CItemState : public CState CItemState(CCharEntity* PEntity, uint16 targid, uint8 loc, uint8 slotid); void UpdateTarget(CBaseEntity* target) override; void UpdateTarget(uint16 targid) override; - bool Update(time_point tick) override; - void Cleanup(time_point tick) override; + bool Update(timer::time_point tick) override; + void Cleanup(timer::time_point tick) override; bool CanChangeState() override; bool CanFollowPath() override { @@ -59,15 +59,15 @@ class CItemState : public CState protected: bool HasMoved(); - CCharEntity* m_PEntity; - CItemUsable* m_PItem; - uint8 m_location; - uint8 m_slot; - duration m_castTime{}; - duration m_animationTime{}; - position_t m_startPos; - bool m_interrupted{ false }; - bool m_interruptable{ true }; + CCharEntity* m_PEntity; + CItemUsable* m_PItem; + uint8 m_location; + uint8 m_slot; + timer::duration m_castTime{}; + timer::duration m_animationTime{}; + position_t m_startPos; + bool m_interrupted{ false }; + bool m_interruptable{ true }; }; #endif diff --git a/src/map/ai/states/magic_state.cpp b/src/map/ai/states/magic_state.cpp index 3c8164829ee..56395f5c7c7 100644 --- a/src/map/ai/states/magic_state.cpp +++ b/src/map/ai/states/magic_state.cpp @@ -82,7 +82,7 @@ CMagicState::CMagicState(CBattleEntity* PEntity, uint16 targid, SpellID spellid, errorMsg == 1 ? MSGBASIC_CANNOT_CAST_SPELL : errorMsg)); } - m_castTime = std::chrono::milliseconds(battleutils::CalculateSpellCastTime(m_PEntity, this)); + m_castTime = battleutils::CalculateSpellCastTime(m_PEntity, this); m_startPos = m_PEntity->loc.p; action_t action; @@ -112,7 +112,7 @@ CMagicState::CMagicState(CBattleEntity* PEntity, uint16 targid, SpellID spellid, m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(action)); } -bool CMagicState::Update(time_point tick) +bool CMagicState::Update(timer::time_point tick) { action_t action; auto* PTarget = m_PEntity->IsValidTarget(m_targid, m_PSpell->getValidTarget(), m_errorMsg); @@ -183,7 +183,7 @@ bool CMagicState::Update(time_point tick) if (!luautils::OnTrustSpellCastCheckBattlefieldTrusts(PChar)) { m_PEntity->OnCastInterrupted(*this, action, MSGBASIC_TRUST_NO_CAST_TRUST, true); - action.recast = 2; // seems hardcoded to 2 + action.recast = 2s; // seems hardcoded to 2 m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(action)); Complete(); @@ -225,7 +225,7 @@ bool CMagicState::Update(time_point tick) { action_t interruptedAction; m_PEntity->setActionInterrupted(interruptedAction, PTarget, MSGBASIC_IS_PARALYZED_2, static_cast(m_PSpell->getID())); - interruptedAction.recast = 2; // seems hardcoded to 2 + interruptedAction.recast = 2s; // seems hardcoded to 2 interruptedAction.actionid = static_cast(m_PSpell->getID()); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(interruptedAction)); @@ -235,7 +235,7 @@ bool CMagicState::Update(time_point tick) // Spell interrupts when you're moving send a message + stop casting fourcc command and not two actions. action.id = m_PEntity->id; action.spellgroup = m_PSpell->getSpellGroup(); - action.recast = 2; + action.recast = 2s; action.actiontype = ACTION_MAGIC_INTERRUPT; actionList_t& actionList = action.getNewActionList(); @@ -254,14 +254,14 @@ bool CMagicState::Update(time_point tick) { action_t interruptedAction; m_PEntity->setActionInterrupted(interruptedAction, PTarget, MSGBASIC_IS_INTIMIDATED, static_cast(m_PSpell->getID())); - interruptedAction.recast = 2; // seems hardcoded to 2 + interruptedAction.recast = 2s; // seems hardcoded to 2 interruptedAction.actionid = static_cast(m_PSpell->getID()); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(interruptedAction)); // See comment in above block for paralyze action.id = m_PEntity->id; action.spellgroup = m_PSpell->getSpellGroup(); - action.recast = 2; + action.recast = 2s; action.actiontype = ACTION_MAGIC_INTERRUPT; actionList_t& actionList = action.getNewActionList(); @@ -292,7 +292,7 @@ bool CMagicState::Update(time_point tick) Complete(); } - else if (IsCompleted() && tick > GetEntryTime() + m_castTime + std::chrono::milliseconds(m_PSpell->getAnimationTime())) + else if (IsCompleted() && tick > GetEntryTime() + m_castTime + m_PSpell->getAnimationTime()) { if (m_PEntity->objtype == TYPE_PC) { @@ -305,7 +305,7 @@ bool CMagicState::Update(time_point tick) return false; } -void CMagicState::Cleanup(time_point tick) +void CMagicState::Cleanup(timer::time_point tick) { if (!IsCompleted()) { @@ -466,16 +466,14 @@ void CMagicState::SpendCost() } } -uint32 CMagicState::GetRecast() +timer::duration CMagicState::GetRecast() { - uint32 RecastTime = 0; - if (!m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_CHAINSPELL) && !m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_SPONTANEITY) && !m_instantCast) { - RecastTime = battleutils::CalculateSpellRecastTime(m_PEntity, GetSpell()); + return battleutils::CalculateSpellRecastTime(m_PEntity, GetSpell()); } - return RecastTime; + return 0s; } void CMagicState::ApplyEnmity(CBattleEntity* PTarget, int ce, int ve) diff --git a/src/map/ai/states/magic_state.h b/src/map/ai/states/magic_state.h index 03ca681abd0..11db4aeab03 100644 --- a/src/map/ai/states/magic_state.h +++ b/src/map/ai/states/magic_state.h @@ -38,8 +38,8 @@ class CMagicState : public CState { public: CMagicState(CBattleEntity* PEntity, uint16 targid, SpellID spellid, uint8 flags = 0); - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; virtual bool CanChangeState() override; virtual bool CanFollowPath() override { @@ -53,10 +53,10 @@ class CMagicState : public CState CSpell* GetSpell(); virtual void TryInterrupt(CBattleEntity* PAttacker) override; - void SpendCost(); - uint32 GetRecast(); - void ApplyEnmity(CBattleEntity* PTarget, int ce, int ve); - void ApplyMagicCoverEnmity(CBattleEntity* PCoverAbilityTarget, CBattleEntity* PCoverAbilityUser, CMobEntity* PMob); + void SpendCost(); + timer::duration GetRecast(); + void ApplyEnmity(CBattleEntity* PTarget, int ce, int ve); + void ApplyMagicCoverEnmity(CBattleEntity* PCoverAbilityTarget, CBattleEntity* PCoverAbilityUser, CMobEntity* PMob); void SetInstantCast(bool const bInstantCast) { @@ -77,7 +77,7 @@ class CMagicState : public CState CBattleEntity* const m_PEntity; std::unique_ptr m_PSpell; - duration m_castTime{}; + timer::duration m_castTime{}; position_t m_startPos; bool m_interrupted{ false }; bool m_instantCast{ false }; diff --git a/src/map/ai/states/mobskill_state.cpp b/src/map/ai/states/mobskill_state.cpp index 0f096981ebd..7e063b25571 100644 --- a/src/map/ai/states/mobskill_state.cpp +++ b/src/map/ai/states/mobskill_state.cpp @@ -61,7 +61,7 @@ CMobSkillState::CMobSkillState(CBattleEntity* PEntity, uint16 targid, uint16 wsi m_PSkill = std::make_unique(*skill); - m_castTime = std::chrono::milliseconds(m_PSkill->getActivationTime()); + m_castTime = m_PSkill->getActivationTime(); if (m_castTime > 0s) { @@ -117,7 +117,7 @@ void CMobSkillState::SpendCost() } } -bool CMobSkillState::Update(time_point tick) +bool CMobSkillState::Update(timer::time_point tick) { // Rotate towards target during ability // TODO : add force param to turnTowardsTarget on certain TP moves like Petro Eyes if (m_castTime > 0s && tick < GetEntryTime() + m_castTime) @@ -134,8 +134,7 @@ bool CMobSkillState::Update(time_point tick) action_t action; m_PEntity->OnMobSkillFinished(*this, action); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(action)); - auto delay = std::chrono::milliseconds(m_PSkill->getAnimationTime()); - m_finishTime = tick + delay; + m_finishTime = tick + m_PSkill->getAnimationTime(); Complete(); } if (IsCompleted() && tick > m_finishTime) @@ -164,7 +163,7 @@ bool CMobSkillState::Update(time_point tick) return false; } -void CMobSkillState::Cleanup(time_point tick) +void CMobSkillState::Cleanup(timer::time_point tick) { if (m_PEntity && m_PEntity->isAlive() && !IsCompleted()) { diff --git a/src/map/ai/states/mobskill_state.h b/src/map/ai/states/mobskill_state.h index 33162c3c3de..e3eaeb0f1ca 100644 --- a/src/map/ai/states/mobskill_state.h +++ b/src/map/ai/states/mobskill_state.h @@ -52,15 +52,15 @@ class CMobSkillState : public CState { return true; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; void SpendCost(); private: CBattleEntity* const m_PEntity; std::unique_ptr m_PSkill; - time_point m_finishTime; - duration m_castTime{}; + timer::time_point m_finishTime; + timer::duration m_castTime{}; int16 m_spentTP; }; diff --git a/src/map/ai/states/petskill_state.cpp b/src/map/ai/states/petskill_state.cpp index 3055c78b754..753b51e7ec2 100644 --- a/src/map/ai/states/petskill_state.cpp +++ b/src/map/ai/states/petskill_state.cpp @@ -60,7 +60,7 @@ CPetSkillState::CPetSkillState(CPetEntity* PEntity, uint16 targid, uint16 wsid) m_PSkill = std::make_unique(*skill); - m_castTime = std::chrono::milliseconds(m_PSkill->getActivationTime()); + m_castTime = m_PSkill->getActivationTime(); if (m_castTime > 0s) { @@ -98,15 +98,14 @@ void CPetSkillState::SpendCost() } } -bool CPetSkillState::Update(time_point tick) +bool CPetSkillState::Update(timer::time_point tick) { if (m_PEntity && m_PEntity->isAlive() && (tick > GetEntryTime() + m_castTime && !IsCompleted())) { action_t action; m_PEntity->OnPetSkillFinished(*this, action); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(action)); - auto delay = std::chrono::milliseconds(m_PSkill->getAnimationTime()); - m_finishTime = tick + delay; + m_finishTime = tick + m_PSkill->getAnimationTime(); Complete(); } if (IsCompleted() && tick > m_finishTime) @@ -135,7 +134,7 @@ bool CPetSkillState::Update(time_point tick) return false; } -void CPetSkillState::Cleanup(time_point tick) +void CPetSkillState::Cleanup(timer::time_point tick) { if (m_PEntity && m_PEntity->isAlive() && !IsCompleted()) { diff --git a/src/map/ai/states/petskill_state.h b/src/map/ai/states/petskill_state.h index 5f78cd4f24a..5171d6dd1f6 100644 --- a/src/map/ai/states/petskill_state.h +++ b/src/map/ai/states/petskill_state.h @@ -52,15 +52,15 @@ class CPetSkillState : public CState { return true; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; void SpendCost(); private: CPetEntity* const m_PEntity; std::unique_ptr m_PSkill; - time_point m_finishTime; - duration m_castTime{}; + timer::time_point m_finishTime; + timer::duration m_castTime{}; int16 m_spentTP; }; diff --git a/src/map/ai/states/raise_state.cpp b/src/map/ai/states/raise_state.cpp index a76ebeb2853..1f6850e2573 100644 --- a/src/map/ai/states/raise_state.cpp +++ b/src/map/ai/states/raise_state.cpp @@ -30,7 +30,7 @@ CRaiseState::CRaiseState(CBattleEntity* PEntity) { } -bool CRaiseState::Update(time_point tick) +bool CRaiseState::Update(timer::time_point tick) { if (!IsCompleted()) { diff --git a/src/map/ai/states/raise_state.h b/src/map/ai/states/raise_state.h index 93e111a1493..ffc947b9372 100644 --- a/src/map/ai/states/raise_state.h +++ b/src/map/ai/states/raise_state.h @@ -30,9 +30,9 @@ class CRaiseState : public CState CRaiseState(CBattleEntity* PEntity); // state logic done per tick - returns whether to exit the state or not - virtual bool Update(time_point tick) override; + virtual bool Update(timer::time_point tick) override; - virtual void Cleanup(time_point tick) override + virtual void Cleanup(timer::time_point tick) override { } // whether the state can be changed by normal means diff --git a/src/map/ai/states/range_state.cpp b/src/map/ai/states/range_state.cpp index e4d09032b41..363b9071cad 100644 --- a/src/map/ai/states/range_state.cpp +++ b/src/map/ai/states/range_state.cpp @@ -129,7 +129,7 @@ bool CRangeState::CanChangeState() return false; } -bool CRangeState::Update(time_point tick) +bool CRangeState::Update(timer::time_point tick) { if (m_PEntity && m_PEntity->isAlive() && (tick > GetEntryTime() + m_aimTime && !IsCompleted())) { @@ -159,7 +159,7 @@ bool CRangeState::Update(time_point tick) PChar->pushPacket(m_errorMsg->copy()); } // reset aim time so interrupted players only have to wait the correct 2.7s until next shot - m_aimTime = std::chrono::seconds(0); + m_aimTime = 0s; m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, std::make_unique(action)); m_PEntity->PAI->EventHandler.triggerListener("RANGE_STATE_EXIT", m_PEntity, nullptr, &action); } @@ -187,7 +187,7 @@ bool CRangeState::Update(time_point tick) return false; } -void CRangeState::Cleanup(time_point tick) +void CRangeState::Cleanup(timer::time_point tick) { } diff --git a/src/map/ai/states/range_state.h b/src/map/ai/states/range_state.h index d4d75e59920..2fc2b07a786 100644 --- a/src/map/ai/states/range_state.h +++ b/src/map/ai/states/range_state.h @@ -46,18 +46,18 @@ class CRangeState : public CState { return true; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; bool CanUseRangedAttack(CBattleEntity* PTarget, bool isEndOfAttack); bool HasMoved(); private: - CBattleEntity* const m_PEntity; - duration m_aimTime{}; // The calculated "phase 1" delay based on weapon and job trait reductions - const duration m_returnWeaponDelay = std::chrono::milliseconds(1000); // Phase 2: Putting the weapon back after a shot (time between shot and being able to move) - const duration m_freePhaseTime = std::chrono::milliseconds(1100); // Phase 3: The cooldown after a ranged attack is executed. (time after being able to move befer you stop getting "you must wait longer" when attempting to Range Attack again) - bool m_rapidShot{ false }; - position_t m_startPos; + CBattleEntity* const m_PEntity; + timer::duration m_aimTime{}; // The calculated "phase 1" delay based on weapon and job trait reductions + const timer::duration m_returnWeaponDelay = 1000ms; // Phase 2: Putting the weapon back after a shot (time between shot and being able to move) + const timer::duration m_freePhaseTime = 1100ms; // Phase 3: The cooldown after a ranged attack is executed. (time after being able to move befer you stop getting "you must wait longer" when attempting to Range Attack again) + bool m_rapidShot{ false }; + position_t m_startPos; }; #endif diff --git a/src/map/ai/states/respawn_state.cpp b/src/map/ai/states/respawn_state.cpp index dc517ae7cda..cac8cb38145 100644 --- a/src/map/ai/states/respawn_state.cpp +++ b/src/map/ai/states/respawn_state.cpp @@ -24,13 +24,13 @@ #include "entities/baseentity.h" #include "entities/mobentity.h" -CRespawnState::CRespawnState(CBaseEntity* _PEntity, duration spawnTime) +CRespawnState::CRespawnState(CBaseEntity* _PEntity, timer::duration spawnTime) : CState(_PEntity, _PEntity->targid) , m_spawnTime(spawnTime) { } -bool CRespawnState::Update(time_point tick) +bool CRespawnState::Update(timer::time_point tick) { // make sure that the respawn time is up to date auto* PMob = dynamic_cast(m_PEntity); @@ -45,9 +45,9 @@ bool CRespawnState::Update(time_point tick) } else { - if (std::chrono::milliseconds(PMob->m_RespawnTime) != m_spawnTime) + if (PMob->m_RespawnTime != m_spawnTime) { - m_spawnTime = std::chrono::milliseconds(PMob->m_RespawnTime); + m_spawnTime = PMob->m_RespawnTime; } } } @@ -59,7 +59,7 @@ bool CRespawnState::Update(time_point tick) return false; } -void CRespawnState::Cleanup(time_point tick) +void CRespawnState::Cleanup(timer::time_point tick) { } diff --git a/src/map/ai/states/respawn_state.h b/src/map/ai/states/respawn_state.h index ad145f9da7d..18ca2ba0790 100644 --- a/src/map/ai/states/respawn_state.h +++ b/src/map/ai/states/respawn_state.h @@ -27,9 +27,9 @@ class CRespawnState : public CState { public: - CRespawnState(CBaseEntity* PEntity, duration spawnTime); - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + CRespawnState(CBaseEntity* PEntity, timer::duration spawnTime); + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; virtual bool CanChangeState() override; virtual bool CanFollowPath() override { @@ -41,7 +41,7 @@ class CRespawnState : public CState } private: - duration m_spawnTime; + timer::duration m_spawnTime; }; #endif diff --git a/src/map/ai/states/state.cpp b/src/map/ai/states/state.cpp index 0601a03eaad..e262f133b29 100644 --- a/src/map/ai/states/state.cpp +++ b/src/map/ai/states/state.cpp @@ -55,14 +55,14 @@ void CState::Complete() m_completed = true; } -time_point CState::GetEntryTime() const +timer::time_point CState::GetEntryTime() const { return m_entryTime; } void CState::ResetEntryTime() { - m_entryTime = server_clock::now(); + m_entryTime = timer::now(); } void CState::SetTarget(uint16 _targid) @@ -91,7 +91,7 @@ auto CState::GetErrorMsg() -> std::unique_ptr return std::unique_ptr(); } -bool CState::DoUpdate(time_point tick) +bool CState::DoUpdate(timer::time_point tick) { UpdateTarget(m_targid); return Update(tick); diff --git a/src/map/ai/states/state.h b/src/map/ai/states/state.h index d16cc90d2d4..8eb03ccdd74 100644 --- a/src/map/ai/states/state.h +++ b/src/map/ai/states/state.h @@ -24,6 +24,7 @@ #define _CSTATE_H #include "common/mmo.h" +#include "common/timer.h" #include "packets/message_basic.h" #include @@ -54,14 +55,14 @@ class CState auto GetErrorMsg() -> std::unique_ptr; - bool DoUpdate(time_point tick); + bool DoUpdate(timer::time_point tick); // try interrupt (on hit) virtual void TryInterrupt(CBattleEntity* PAttacker) { } // called when state completes - virtual void Cleanup(time_point tick) = 0; + virtual void Cleanup(timer::time_point tick) = 0; // whether the state can be changed by normal means virtual bool CanChangeState() = 0; virtual bool CanFollowPath() = 0; @@ -72,13 +73,13 @@ class CState protected: // state logic done per tick - returns whether to exit the state or not - virtual bool Update(time_point tick) = 0; + virtual bool Update(timer::time_point tick) = 0; virtual void UpdateTarget(uint16 targid); virtual void UpdateTarget(CBaseEntity* target); - uint16 GetTargetID() const; - void Complete(); - time_point GetEntryTime() const; + uint16 GetTargetID() const; + void Complete(); + timer::time_point GetEntryTime() const; std::unique_ptr m_errorMsg; @@ -86,9 +87,9 @@ class CState uint16 m_targid{ 0 }; private: - CBaseEntity* m_PTarget{ nullptr }; - bool m_completed{ false }; - time_point m_entryTime{ server_clock::now() }; + CBaseEntity* m_PTarget{ nullptr }; + bool m_completed{ false }; + timer::time_point m_entryTime{ timer::now() }; }; #endif diff --git a/src/map/ai/states/synth_state.cpp b/src/map/ai/states/synth_state.cpp index a8b6d52709f..22943f685d0 100644 --- a/src/map/ai/states/synth_state.cpp +++ b/src/map/ai/states/synth_state.cpp @@ -64,7 +64,7 @@ CSynthState::CSynthState(CCharEntity* PChar, SKILLTYPE skill) } } -bool CSynthState::Update(time_point tick) +bool CSynthState::Update(timer::time_point tick) { if (SynthReady()) { @@ -78,7 +78,7 @@ bool CSynthState::Update(time_point tick) return false; } -void CSynthState::Cleanup(time_point tick) +void CSynthState::Cleanup(timer::time_point tick) { std::ignore = tick; } diff --git a/src/map/ai/states/synth_state.h b/src/map/ai/states/synth_state.h index 9898dcabd77..294c02b497c 100644 --- a/src/map/ai/states/synth_state.h +++ b/src/map/ai/states/synth_state.h @@ -31,9 +31,9 @@ class CSynthState : public CState CSynthState(CCharEntity* PChar, SKILLTYPE skill); // state logic done per tick - returns whether to exit the state or not - virtual bool Update(time_point tick) override; + virtual bool Update(timer::time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; // whether the state can be changed by normal means virtual bool CanChangeState() override { @@ -56,7 +56,7 @@ class CSynthState : public CState private: CCharEntity* const m_PEntity; - duration m_synthFinishTime{ 16s }; + timer::duration m_synthFinishTime{ 16s }; }; #endif diff --git a/src/map/ai/states/trigger_state.cpp b/src/map/ai/states/trigger_state.cpp index b21c5242364..4b6017d21f2 100644 --- a/src/map/ai/states/trigger_state.cpp +++ b/src/map/ai/states/trigger_state.cpp @@ -32,7 +32,7 @@ CTriggerState::CTriggerState(CBaseEntity* PEntity, uint16 targid, bool door) { } -bool CTriggerState::Update(time_point tick) +bool CTriggerState::Update(timer::time_point tick) { if (!IsCompleted()) { diff --git a/src/map/ai/states/trigger_state.h b/src/map/ai/states/trigger_state.h index 01cffb6ecc9..3f9bfaf8b61 100644 --- a/src/map/ai/states/trigger_state.h +++ b/src/map/ai/states/trigger_state.h @@ -28,8 +28,8 @@ class CTriggerState : public CState { public: CTriggerState(CBaseEntity* PEntity, uint16 targid, bool door = false); - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override { } virtual bool CanChangeState() override; diff --git a/src/map/ai/states/weaponskill_state.cpp b/src/map/ai/states/weaponskill_state.cpp index 6f2090ff429..feaa2db8087 100644 --- a/src/map/ai/states/weaponskill_state.cpp +++ b/src/map/ai/states/weaponskill_state.cpp @@ -113,7 +113,7 @@ void CWeaponSkillState::SpendCost() m_spent = tp; } -bool CWeaponSkillState::Update(time_point tick) +bool CWeaponSkillState::Update(timer::time_point tick) { if (m_PEntity && m_PEntity->isAlive() && !IsCompleted()) { @@ -196,7 +196,7 @@ bool CWeaponSkillState::Update(time_point tick) return false; } -void CWeaponSkillState::Cleanup(time_point tick) +void CWeaponSkillState::Cleanup(timer::time_point tick) { // TODO: interrupt an in progress ws } diff --git a/src/map/ai/states/weaponskill_state.h b/src/map/ai/states/weaponskill_state.h index ffd9f74b136..fc4e8eaf724 100644 --- a/src/map/ai/states/weaponskill_state.h +++ b/src/map/ai/states/weaponskill_state.h @@ -50,14 +50,14 @@ class CWeaponSkillState : public CState { return true; } - virtual bool Update(time_point tick) override; - virtual void Cleanup(time_point tick) override; + virtual bool Update(timer::time_point tick) override; + virtual void Cleanup(timer::time_point tick) override; void SpendCost(); private: CBattleEntity* const m_PEntity; std::unique_ptr m_PSkill; - time_point m_finishTime; + timer::time_point m_finishTime; int16 m_spent{ 0 }; }; diff --git a/src/map/attack.cpp b/src/map/attack.cpp index d11cc73ffaa..81244a796f1 100644 --- a/src/map/attack.cpp +++ b/src/map/attack.cpp @@ -593,7 +593,16 @@ void CAttack::ProcessDamage() { m_naturalH2hDamage = (int32)(m_attacker->GetSkill(SKILL_HAND_TO_HAND) * 0.11f) + 3; m_baseDamage = m_attacker->GetMainWeaponDmg(); - m_damage = (uint32)(((m_baseDamage + m_naturalH2hDamage + m_bonusBasePhysicalDamage + battleutils::GetFSTR(m_attacker, m_victim, slot)) * m_damageRatio)); + + if (m_attackType == PHYSICAL_ATTACK_TYPE::KICK) + { + int32 kickDamage = m_naturalH2hDamage + m_attacker->getMod(Mod::KICK_DMG); // KICK_DMG includes weapon dmg if footwork is active + m_damage = (uint32)(((kickDamage + m_bonusBasePhysicalDamage + battleutils::GetFSTR(m_attacker, m_victim, slot)) * m_damageRatio)); + } + else + { + m_damage = (uint32)(((m_baseDamage + m_naturalH2hDamage + m_bonusBasePhysicalDamage + battleutils::GetFSTR(m_attacker, m_victim, slot)) * m_damageRatio)); + } } else if (slot == SLOT_MAIN) { diff --git a/src/map/battlefield.cpp b/src/map/battlefield.cpp index 44536fec4ef..12ebdd47a8b 100644 --- a/src/map/battlefield.cpp +++ b/src/map/battlefield.cpp @@ -60,7 +60,7 @@ CBattlefield::CBattlefield(uint16 id, CZone* PZone, uint8 area, CCharEntity* PIn , m_Area(area) , m_Record(BattlefieldRecord_t()) , m_Rules(0) -, m_StartTime(server_clock::now()) +, m_StartTime(timer::now()) , m_LastPromptTime(0s) , m_MaxParticipants(8) , m_LevelCap(0) @@ -124,42 +124,42 @@ uint16 CBattlefield::GetRuleMask() const return m_Rules; } -time_point CBattlefield::GetStartTime() const +timer::time_point CBattlefield::GetStartTime() const { return m_StartTime; } -duration CBattlefield::GetTimeInside() const +timer::duration CBattlefield::GetTimeInside() const { return m_Tick - m_StartTime; } -time_point CBattlefield::GetFightTime() const +timer::time_point CBattlefield::GetFightTime() const { return m_FightTick; } -duration CBattlefield::GetTimeLimit() const +timer::duration CBattlefield::GetTimeLimit() const { return m_TimeLimit; } -time_point CBattlefield::GetWipeTime() const +timer::time_point CBattlefield::GetWipeTime() const { return m_WipeTime; } -duration CBattlefield::GetFinishTime() const +timer::duration CBattlefield::GetFinishTime() const { return m_FinishTime; } -duration CBattlefield::GetRemainingTime() const +timer::duration CBattlefield::GetRemainingTime() const { - return GetTimeLimit() > GetTimeInside() ? GetTimeLimit() - GetTimeInside() : duration(0); + return GetTimeLimit() > GetTimeInside() ? GetTimeLimit() - GetTimeInside() : timer::duration(0); } -duration CBattlefield::GetLastTimeUpdate() const +timer::duration CBattlefield::GetLastTimeUpdate() const { return m_LastPromptTime; } @@ -200,7 +200,7 @@ void CBattlefield::SetInitiator(std::string const& name) m_Initiator.name = name; } -void CBattlefield::SetTimeLimit(duration time) +void CBattlefield::SetTimeLimit(timer::duration time) { m_TimeLimit = time; m_LastPromptTime = time; @@ -214,7 +214,7 @@ void CBattlefield::SetTimeLimit(duration time) } } -void CBattlefield::SetWipeTime(time_point time) +void CBattlefield::SetWipeTime(timer::time_point time) { m_WipeTime = time; } @@ -224,7 +224,7 @@ void CBattlefield::SetArea(uint8 area) m_Area = area; } -void CBattlefield::SetRecord(std::string const& name, duration time, size_t partySize) +void CBattlefield::SetRecord(std::string const& name, timer::duration time, size_t partySize) { m_Record.name = !name.empty() ? name : m_Initiator.name; m_Record.time = time; @@ -257,7 +257,7 @@ void CBattlefield::SetLocalVar(std::string const& name, uint64_t value) m_LocalVars[name] = value; } -void CBattlefield::SetLastTimeUpdate(duration time) +void CBattlefield::SetLastTimeUpdate(timer::duration time) { m_LastPromptTime = time; } @@ -283,7 +283,7 @@ void CBattlefield::ApplyLevelRestrictions(CCharEntity* PChar) const } PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE, EffectNotice::Silent); - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, cap, 0, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, cap, 0s, 0s)); } else { @@ -293,7 +293,7 @@ void CBattlefield::ApplyLevelRestrictions(CCharEntity* PChar) const // Check if we should remove SJ, whether or not there is a lv cap. if (!(m_Rules & BCRULES::RULES_ALLOW_SUBJOBS)) { - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SJ_RESTRICTION, EFFECT_SJ_RESTRICTION, 0, 0, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SJ_RESTRICTION, EFFECT_SJ_RESTRICTION, 0, 0s, 0s)); } } @@ -430,7 +430,7 @@ bool CBattlefield::InsertEntity(CBaseEntity* PEntity, bool enter, BATTLEFIELDMOB else { entity->StatusEffectContainer->AddStatusEffect( - new CStatusEffect(EFFECT_BATTLEFIELD, EFFECT_BATTLEFIELD, this->GetID(), 0, 0, m_Initiator.id, this->GetArea()), EffectNotice::Silent); + new CStatusEffect(EFFECT_BATTLEFIELD, EFFECT_BATTLEFIELD, this->GetID(), 0s, 0s, m_Initiator.id, this->GetArea()), EffectNotice::Silent); } } @@ -672,7 +672,7 @@ bool CBattlefield::RemoveEntity(CBaseEntity* PEntity, uint8 leavecode) return found; } -void CBattlefield::onTick(time_point time) +void CBattlefield::onTick(timer::time_point time) { TracyZoneScoped; if (!m_Attacked) @@ -701,7 +701,7 @@ bool CBattlefield::CanCleanup(bool cleanup) return m_Cleanup || m_EnteredPlayers.empty(); } -bool CBattlefield::Cleanup(time_point time, bool force) +bool CBattlefield::Cleanup(timer::time_point time, bool force) { // Wait until if (!force && !m_EnteredPlayers.empty() && m_cleanupTime > time) @@ -815,12 +815,12 @@ bool CBattlefield::Cleanup(time_point time, bool force) if (rset && rset->rowsCount() && rset->next()) { const auto fastestTime = rset->get("fastestTime"); - updateRecord = fastestTime > std::chrono::duration_cast(m_Record.time).count(); + updateRecord = fastestTime > timer::count_seconds(m_Record.time); } if (updateRecord) { - const uint32 timeThing = std::chrono::duration_cast(m_Record.time).count(); + const uint32 timeThing = timer::count_seconds(m_Record.time); db::preparedStmt("UPDATE bcnm_records SET fastestName = ?, fastestTime = ?, fastestPartySize = ? WHERE bcnmId = ? AND zoneid = ?", m_Record.name, timeThing, m_Record.partySize, this->GetID(), GetZoneID()); diff --git a/src/map/battlefield.h b/src/map/battlefield.h index ae648c11016..c71707534af 100644 --- a/src/map/battlefield.h +++ b/src/map/battlefield.h @@ -29,6 +29,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" +#include "common/timer.h" #include "sol/sol.hpp" #include @@ -94,13 +95,13 @@ struct BattlefieldMob_t struct BattlefieldRecord_t { - std::string name; - size_t partySize; - duration time; + std::string name; + size_t partySize; + timer::duration time; BattlefieldRecord_t() : partySize(0) - , time(std::chrono::minutes(30)) + , time(30min) { } }; @@ -141,17 +142,17 @@ class CBattlefield : public std::enable_shared_from_this const BattlefieldRecord_t& GetRecord() const; uint8 GetStatus() const; uint16 GetRuleMask() const; - time_point GetStartTime() const; - duration GetTimeInside() const; - time_point GetFightTime() const; - duration GetTimeLimit() const; - time_point GetWipeTime() const; + timer::time_point GetStartTime() const; + timer::duration GetTimeInside() const; + timer::time_point GetFightTime() const; + timer::duration GetTimeLimit() const; + timer::time_point GetWipeTime() const; size_t GetMaxParticipants() const; size_t GetPlayerCount() const; uint8 GetLevelCap() const; - duration GetFinishTime() const; - duration GetRemainingTime() const; - duration GetLastTimeUpdate() const; + timer::duration GetFinishTime() const; + timer::duration GetRemainingTime() const; + timer::duration GetLastTimeUpdate() const; uint64_t GetLocalVar(std::string const& name) const; uint32 GetArmouryCrate() const; @@ -169,15 +170,15 @@ class CBattlefield : public std::enable_shared_from_this void SetName(std::string const& name); void SetInitiator(std::string const& name); void SetArea(uint8 area); - void SetRecord(std::string const& name, duration time, size_t partySize); + void SetRecord(std::string const& name, timer::duration time, size_t partySize); void SetStatus(uint8 status); void SetRuleMask(uint16 rulemask); - void SetTimeLimit(duration time); - void SetWipeTime(time_point time); + void SetTimeLimit(timer::duration time); + void SetWipeTime(timer::time_point time); void SetMaxParticipants(uint8 max); void SetLevelCap(uint8 cap); void SetLocalVar(std::string const& name, uint64_t value); - void SetLastTimeUpdate(duration time); + void SetLastTimeUpdate(timer::duration time); void setArmouryCrate(uint32 entityId); void ApplyLevelRestrictions(CCharEntity* PChar) const; @@ -185,9 +186,9 @@ class CBattlefield : public std::enable_shared_from_this CBaseEntity* GetEntity(CBaseEntity* PEntity); bool IsRegistered(CCharEntity* PChar); bool RemoveEntity(CBaseEntity* PEntity, uint8 leavecode = 0); - void onTick(time_point time); + void onTick(timer::time_point time); bool CanCleanup(bool cleanup = false); - bool Cleanup(time_point time, bool force); + bool Cleanup(timer::time_point time, bool force); // Groups void addGroup(BattlefieldGroup group); @@ -217,22 +218,22 @@ class CBattlefield : public std::enable_shared_from_this BattlefieldRecord_t m_Record; uint8 m_Status{ BATTLEFIELD_STATUS_OPEN }; uint16 m_Rules; - time_point m_StartTime; - time_point m_Tick; - time_point m_FightTick; - duration m_TimeLimit{}; - time_point m_WipeTime; - duration m_FinishTime{}; - duration m_LastPromptTime{}; + timer::time_point m_StartTime; + timer::time_point m_Tick; + timer::time_point m_FightTick; + timer::duration m_TimeLimit{}; + timer::time_point m_WipeTime; + timer::duration m_FinishTime{}; + timer::duration m_LastPromptTime{}; size_t m_MaxParticipants; uint8 m_LevelCap; // Entity id of the Armoury Crate that appears upon victory uint32 m_armouryCrate = 0; - time_point m_cleanupTime{}; - bool m_cleanedPlayers = false; - bool m_Cleanup = false; - bool m_Attacked = false; + timer::time_point m_cleanupTime{}; + bool m_cleanedPlayers = false; + bool m_Cleanup = false; + bool m_Attacked = false; std::unordered_map m_LocalVars; std::vector m_groups; diff --git a/src/map/battlefield_handler.cpp b/src/map/battlefield_handler.cpp index 69a7934b8b2..13076ab52ec 100644 --- a/src/map/battlefield_handler.cpp +++ b/src/map/battlefield_handler.cpp @@ -54,7 +54,7 @@ CBattlefieldHandler::CBattlefieldHandler(CZone* PZone) { } -void CBattlefieldHandler::HandleBattlefields(time_point tick) +void CBattlefieldHandler::HandleBattlefields(timer::time_point tick) { TracyZoneScoped; // todo: use raw pointers otherwise might be harming lua @@ -158,7 +158,7 @@ uint8 CBattlefieldHandler::LoadBattlefield(CCharEntity* PChar, const Battlefield if (!PChar->StatusEffectContainer->GetStatusEffect(EFFECT_BATTLEFIELD)) { PChar->StatusEffectContainer->AddStatusEffect( - new CStatusEffect(EFFECT_BATTLEFIELD, EFFECT_BATTLEFIELD, PBattlefield->GetID(), 0, 0, PChar->id, PBattlefield->GetArea()), EffectNotice::Silent); + new CStatusEffect(EFFECT_BATTLEFIELD, EFFECT_BATTLEFIELD, PBattlefield->GetID(), 0s, 0s, PChar->id, PBattlefield->GetArea()), EffectNotice::Silent); } luautils::OnBattlefieldRegister(PChar, PBattlefield); @@ -317,6 +317,6 @@ uint8 CBattlefieldHandler::MaxBattlefieldAreas() const void CBattlefieldHandler::addOrphanedPlayer(CCharEntity* PChar) { - auto orphan = std::make_pair(PChar->id, server_clock::now() + 5s); + auto orphan = std::make_pair(PChar->id, timer::now() + 5s); m_orphanedPlayers.emplace_back(orphan); } diff --git a/src/map/battlefield_handler.h b/src/map/battlefield_handler.h index 858a2b162a3..f039b03e31d 100644 --- a/src/map/battlefield_handler.h +++ b/src/map/battlefield_handler.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" +#include "common/timer.h" #include #include @@ -37,22 +38,22 @@ class CZone; struct BattlefieldRegistration { - uint16 id = -1; - uint8 area = 1; - uint32 initiator = 0; - uint32 maxPlayers = 0; - uint32 levelCap = 0; - uint32 rules = 0; - std::chrono::seconds timeLimit = std::chrono::seconds(0); - bool isMission = false; - bool showTimer = true; + uint16 id = -1; + uint8 area = 1; + uint32 initiator = 0; + uint32 maxPlayers = 0; + uint32 levelCap = 0; + uint32 rules = 0; + timer::duration timeLimit = 0s; + bool isMission = false; + bool showTimer = true; }; class CBattlefieldHandler { public: CBattlefieldHandler(CZone* PZone); - void HandleBattlefields(time_point tick); // called every tick to handle win/lose conditions, locking the bcnm, etc + void HandleBattlefields(timer::time_point tick); // called every tick to handle win/lose conditions, locking the bcnm, etc uint8 LoadBattlefield(CCharEntity* PChar, const BattlefieldRegistration& registration); // attempts to load battlefield, returns BATTLEFIELD_RETURN_CODE CBattlefield* GetBattlefield(CBaseEntity* PEntity, bool checkRegistered = false); // return pointer to battlefield if exists CBattlefield* GetBattlefieldByArea(uint8 area) const; @@ -71,7 +72,7 @@ class CBattlefieldHandler std::map m_ReservedAreas; // // Players that need to be kicked from whatever battlefield they were in - std::vector> m_orphanedPlayers; + std::vector> m_orphanedPlayers; }; #endif diff --git a/src/map/char_recast_container.cpp b/src/map/char_recast_container.cpp index 33b174cddd7..7a074d872a6 100644 --- a/src/map/char_recast_container.cpp +++ b/src/map/char_recast_container.cpp @@ -47,14 +47,14 @@ CCharRecastContainer::CCharRecastContainer(CCharEntity* PChar) * * ************************************************************************/ -void CCharRecastContainer::Add(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime, uint8 maxCharges) +void CCharRecastContainer::Add(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime, uint8 maxCharges) { Recast_t* recast = Load(type, id, duration, chargeTime, maxCharges); if (type == RECAST_ABILITY) { db::preparedStmt("REPLACE INTO char_recast VALUES (?, ?, ?, ?)", - m_PChar->id, recast->ID, static_cast(recast->TimeStamp), recast->RecastTime); + m_PChar->id, recast->ID, earth_time::timestamp(timer::to_utc(recast->TimeStamp)), static_cast(timer::count_seconds(recast->RecastTime))); } } @@ -96,7 +96,7 @@ void CCharRecastContainer::DeleteByIndex(RECASTTYPE type, uint8 index) RecastList_t* PRecastList = GetRecastList(type); if (type == RECAST_ABILITY) { - PRecastList->at(index).RecastTime = 0; + PRecastList->at(index).RecastTime = 0s; db::preparedStmt("DELETE FROM char_recast WHERE charid = ? AND id = ?", m_PChar->id, PRecastList->at(index).ID); } else @@ -166,7 +166,7 @@ void CCharRecastContainer::Check() { Recast_t* recast = &PRecastList->at(i); - if (time(nullptr) >= (recast->TimeStamp + recast->RecastTime)) + if (timer::now() >= recast->TimeStamp + recast->RecastTime) { if (type == RECAST_ITEM) { @@ -184,7 +184,7 @@ void CCharRecastContainer::Check() } else { - recast->RecastTime = 0; + recast->RecastTime = 0s; } } } diff --git a/src/map/char_recast_container.h b/src/map/char_recast_container.h index 7a95debadbf..c23e3bc3cff 100644 --- a/src/map/char_recast_container.h +++ b/src/map/char_recast_container.h @@ -37,7 +37,7 @@ class CCharRecastContainer : public CRecastContainer { } virtual void Check() override; - virtual void Add(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime, uint8 maxCharges) override; + virtual void Add(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime, uint8 maxCharges) override; virtual void Del(RECASTTYPE type) override; virtual void Del(RECASTTYPE type, uint16 id) override; virtual void DeleteByIndex(RECASTTYPE type, uint8 index) override; diff --git a/src/map/conquest_system.cpp b/src/map/conquest_system.cpp index d5f2198c175..7e461b2c3f7 100644 --- a/src/map/conquest_system.cpp +++ b/src/map/conquest_system.cpp @@ -611,12 +611,14 @@ namespace conquest * * ************************************************************************/ - uint8 GetNexTally() + uint8 GetNextTally() { - auto weekday = CVanaTime::getInstance()->getSysWeekDay(); - uint8 dayspassed = (weekday == 0 ? 6 : weekday - 1) * 25; - dayspassed += ((CVanaTime::getInstance()->getSysHour() * 60 + CVanaTime::getInstance()->getSysMinute()) * 25) / 1440; - return (uint8)(175 - dayspassed); + auto nextWeek = earth_time::get_next_game_week(); + auto untilTally = vanadiel_time::from_earth_time(nextWeek) - vanadiel_time::now(); + + auto vanaDaysUntilTally = std::chrono::ceil(untilTally).count(); + + return static_cast(vanaDaysUntilTally); } /************************************************************************ diff --git a/src/map/conquest_system.h b/src/map/conquest_system.h index 113f6ad5cce..f65bb966370 100644 --- a/src/map/conquest_system.h +++ b/src/map/conquest_system.h @@ -67,7 +67,7 @@ namespace conquest uint8 GetAlliance(uint8 sandoria, uint8 bastok, uint8 windurst, // Determine if losing nations are allied uint8 sandoria_prev, uint8 bastok_prev, uint8 windurst_prev); bool IsAlliance(); // Determine if losing nations are allied - uint8 GetNexTally(); // Next tally (weekly or every hour ?) + uint8 GetNextTally(); // Vana'diel days until next weekly conquest tally uint8 GetRegionOwner(REGION_TYPE RegionID); // Get owner of the region uint32 AddConquestPoints(CCharEntity* PChar, uint32 exp); // Add conquest points diff --git a/src/map/enmity_container.cpp b/src/map/enmity_container.cpp index d152e9ced96..a8f5ce36b45 100644 --- a/src/map/enmity_container.cpp +++ b/src/map/enmity_container.cpp @@ -20,6 +20,7 @@ */ #include "common/logging.h" +#include "common/settings.h" #include "common/utils.h" #include "ai/ai_container.h" diff --git a/src/map/entities/baseentity.cpp b/src/map/entities/baseentity.cpp index 50e616e6f61..11975f689a4 100644 --- a/src/map/entities/baseentity.cpp +++ b/src/map/entities/baseentity.cpp @@ -53,7 +53,7 @@ CBaseEntity::CBaseEntity() , PAI(nullptr) , PBattlefield(nullptr) , PInstance(nullptr) -, m_nextUpdateTimer(std::chrono::steady_clock::now()) +, m_nextUpdateTimer(timer::now()) { TracyZoneScoped; speed = baseSpeed; diff --git a/src/map/entities/baseentity.h b/src/map/entities/baseentity.h index b594545f700..fa50b58a554 100644 --- a/src/map/entities/baseentity.h +++ b/src/map/entities/baseentity.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" +#include "common/timer.h" #include "packets/message_basic.h" #include @@ -294,7 +295,7 @@ class CBaseEntity auto GetLocalVars() -> std::map&; // pre-tick update - virtual void Tick(time_point) = 0; + virtual void Tick(timer::time_point) = 0; // post-tick update virtual void PostTick() = 0; @@ -334,7 +335,7 @@ class CBaseEntity CBattlefield* PBattlefield; // pointer to battlefield (if in one) CInstance* PInstance; - std::chrono::steady_clock::time_point m_nextUpdateTimer; // next time the entity should push an update packet + timer::time_point m_nextUpdateTimer; // next time the entity should push an update packet protected: std::map m_localVars; diff --git a/src/map/entities/battleentity.cpp b/src/map/entities/battleentity.cpp index 39b1750fbdb..9d32ecac815 100644 --- a/src/map/entities/battleentity.cpp +++ b/src/map/entities/battleentity.cpp @@ -911,6 +911,24 @@ uint16 CBattleEntity::ATT(SLOTTYPE slot) { ATT += this->GetSkill(SKILL_AUTOMATON_MELEE); } + else if (this->objtype == TYPE_PET) + { + auto getEcoStrBonusFunc = lua["utils"]["getEcosystemStrengthBonus"]; + + if (getEcoStrBonusFunc.valid()) + { + CBattleEntity* thisTarget = nullptr; + if (this->PAI->IsEngaged()) + { + thisTarget = this->GetBattleTarget(); + } + + if (thisTarget != nullptr && (int8)getEcoStrBonusFunc(this->m_EcoSystem, thisTarget->m_EcoSystem) > 0) + { + ATTP += this->getMod(Mod::ENHANCES_MONSTER_CORRELATION); + } + } + } // use max to prevent underflow return std::max(1, ATT + (ATT * ATTP / 100) + std::min((ATT * m_modStat[Mod::FOOD_ATTP] / 100), m_modStat[Mod::FOOD_ATT_CAP])); } @@ -1077,7 +1095,24 @@ uint16 CBattleEntity::ACC(uint8 attackNumber, uint16 offsetAccuracy) ACC += this->PMaster->getMod(Mod::TANDEM_STRIKE_POWER); } } + if (this->objtype == TYPE_PET) + { + auto getEcoStrBonusFunc = lua["utils"]["getEcosystemStrengthBonus"]; + + if (getEcoStrBonusFunc.valid()) + { + CBattleEntity* thisTarget = nullptr; + if (this->PAI->IsEngaged()) + { + thisTarget = this->GetBattleTarget(); + } + if (thisTarget != nullptr && (int8)getEcoStrBonusFunc(this->m_EcoSystem, thisTarget->m_EcoSystem) > 0) + { + ACC += this->getMod(Mod::ENHANCES_MONSTER_CORRELATION); + } + } + } ACC = ACC + std::min((ACC * m_modStat[Mod::FOOD_ACCP] / 100), m_modStat[Mod::FOOD_ACC_CAP]) + DEX() / 2; // Account for food mods here for Snatch Morsel return std::max(0, ACC); } @@ -1969,7 +2004,7 @@ void CBattleEntity::OnCastInterrupted(CMagicState& state, action_t& action, MSGB { action.id = id; action.spellgroup = PSpell->getSpellGroup(); - action.recast = 0; + action.recast = 0s; action.actiontype = ACTION_MAGIC_INTERRUPT; actionList_t& actionList = action.getNewActionList(); @@ -2319,7 +2354,7 @@ bool CBattleEntity::OnAttack(CAttackState& state, action_t& action) } battleutils::ClaimMob(PTarget, this); // Mobs get claimed whether or not your attack actually is intimidated/paralyzed - PTarget->LastAttacked = server_clock::now(); + PTarget->LastAttacked = timer::now(); if (battleutils::IsParalyzed(this)) { @@ -2517,7 +2552,7 @@ bool CBattleEntity::OnAttack(CAttackState& state, action_t& action) // Apply Feint if (CStatusEffect* PFeintEffect = StatusEffectContainer->GetStatusEffect(EFFECT_FEINT)) { - if (PTarget->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_EVASION_DOWN, EFFECT_EVASION_DOWN, PFeintEffect->GetPower(), 3, 30))) + if (PTarget->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_EVASION_DOWN, EFFECT_EVASION_DOWN, PFeintEffect->GetPower(), 3s, 30s))) { auto PEffect = PTarget->StatusEffectContainer->GetStatusEffect(EFFECT_EVASION_DOWN); @@ -2699,14 +2734,14 @@ void CBattleEntity::OnDespawn(CDespawnState& /*unused*/) PAI->Internal_Respawn(0s); } -void CBattleEntity::SetBattleStartTime(time_point time) +void CBattleEntity::SetBattleStartTime(timer::time_point time) { m_battleStartTime = time; } -duration CBattleEntity::GetBattleTime() +timer::duration CBattleEntity::GetBattleTime() { - return server_clock::now() - m_battleStartTime; + return timer::now() - m_battleStartTime; } void CBattleEntity::setBattleID(uint16 battleID) @@ -2719,7 +2754,7 @@ uint16 CBattleEntity::getBattleID() return m_battleID; } -void CBattleEntity::Tick(time_point /*unused*/) +void CBattleEntity::Tick(timer::time_point /*unused*/) { TracyZoneScoped; } diff --git a/src/map/entities/battleentity.h b/src/map/entities/battleentity.h index f584dffb54a..f785cff720f 100644 --- a/src/map/entities/battleentity.h +++ b/src/map/entities/battleentity.h @@ -742,13 +742,13 @@ class CBattleEntity : public CBaseEntity virtual void TryHitInterrupt(CBattleEntity* PAttacker); virtual void OnDespawn(CDespawnState&); - void SetBattleStartTime(time_point); - duration GetBattleTime(); + void SetBattleStartTime(timer::time_point); + timer::duration GetBattleTime(); void setBattleID(uint16 battleID); uint16 getBattleID(); - virtual void Tick(time_point) override; + virtual void Tick(timer::time_point) override; virtual void PostTick() override; health_t health{}; // hp,mp,tp @@ -758,8 +758,8 @@ class CBattleEntity : public CBaseEntity uint16 m_magicEvasion; // store this so it can be removed easily bool m_unkillable; // entity is not able to die (probably until some action removes this flag) - time_point charmTime; // to hold the time entity is charmed - bool isCharmed; // is the battle entity charmed? + timer::time_point charmTime; // to hold the time entity is charmed + bool isCharmed; // is the battle entity charmed? float m_ModelRadius; // The radius of the entity model, for calculating the range of a physical attack ECOSYSTEM m_EcoSystem{}; // Entity eco system @@ -773,25 +773,25 @@ class CBattleEntity : public CBaseEntity ActionList_t m_ActionList{}; // List of actions performed in one attack (you will need to write a structure that includes an ActionList in which there will be categories, animations, etc.) - CParty* PParty; - CBattleEntity* PPet; - CBattleEntity* PMaster; // Owner/owner of the entity (applies to all combat entities) - CBattleEntity* PLastAttacker; - time_point LastAttacked; - battlehistory_t BattleHistory{}; // Stores info related to most recent combat actions taken towards this entity. + CParty* PParty; + CBattleEntity* PPet; + CBattleEntity* PMaster; // Owner/owner of the entity (applies to all combat entities) + CBattleEntity* PLastAttacker; + timer::time_point LastAttacked; + battlehistory_t BattleHistory{}; // Stores info related to most recent combat actions taken towards this entity. std::unique_ptr StatusEffectContainer; std::unique_ptr PRecastContainer; std::unique_ptr PNotorietyContainer; private: - JOBTYPE m_mjob; - JOBTYPE m_sjob; - uint8 m_mlvl; // CURRENT level of the main job - uint8 m_slvl; // CURRENT level of the sub job - uint16 m_battleTarget{ 0 }; - time_point m_battleStartTime; - uint16 m_battleID = 0; // Current battle the entity is participating in. Battle ID must match in order for entities to interact with each other. + JOBTYPE m_mjob; + JOBTYPE m_sjob; + uint8 m_mlvl; // CURRENT level of the main job + uint8 m_slvl; // CURRENT level of the sub job + uint16 m_battleTarget{ 0 }; + timer::time_point m_battleStartTime; + uint16 m_battleID = 0; // Current battle the entity is participating in. Battle ID must match in order for entities to interact with each other. std::unordered_map m_modStat; // array of modifiers std::unordered_map m_modStatSave; // saved state diff --git a/src/map/entities/charentity.cpp b/src/map/entities/charentity.cpp index ea2e374476f..7d023cf8f04 100644 --- a/src/map/entities/charentity.cpp +++ b/src/map/entities/charentity.cpp @@ -97,6 +97,7 @@ #include "weapon_skill.h" CCharEntity::CCharEntity() +: m_PlayTime(0s) { TracyZoneScoped; objtype = TYPE_PC; @@ -190,8 +191,8 @@ CCharEntity::CCharEntity() m_hasArise = false; m_LevelRestriction = 0; m_lastBcnmTimePrompt = 0; - m_AHHistoryTimestamp = 0; - m_DeathTimestamp = 0; + m_AHHistoryTimestamp = timer::time_point::min(); + m_DeathTimestamp = timer::time_point::min(); m_EquipFlag = 0; m_EquipBlock = 0; @@ -232,8 +233,7 @@ CCharEntity::CCharEntity() resetPetZoningInfo(); petZoningInfo.petID = 0; - m_PlayTime = 0; - m_SaveTime = 0; + m_SaveTime = timer::time_point::min(); m_reloadParty = false; m_moghouseID = 0; @@ -604,8 +604,8 @@ void CCharEntity::resetPetZoningInfo() petZoningInfo.petMP = 0; petZoningInfo.respawnPet = false; petZoningInfo.petType = PET_TYPE::AVATAR; - petZoningInfo.jugSpawnTime = 0; - petZoningInfo.jugDuration = 0; + petZoningInfo.jugSpawnTime = timer::time_point::min(); + petZoningInfo.jugDuration = 0s; } bool CCharEntity::shouldPetPersistThroughZoning() @@ -874,17 +874,17 @@ void CCharEntity::setBlockingAid(bool isBlockingAid) m_isBlockingAid = isBlockingAid; } -void CCharEntity::SetPlayTime(uint32 playTime) +void CCharEntity::SetPlayTime(timer::duration playTime) { m_PlayTime = playTime; - m_SaveTime = gettick() / 1000; + m_SaveTime = timer::now(); } -uint32 CCharEntity::GetPlayTime(bool needUpdate) +timer::duration CCharEntity::GetPlayTime(bool needUpdate) { if (needUpdate) { - uint32 currentTime = gettick() / 1000; + auto currentTime = timer::now(); m_PlayTime += currentTime - m_SaveTime; m_SaveTime = currentTime; @@ -1015,7 +1015,7 @@ bool CCharEntity::PersistData() return didPersist; } -bool CCharEntity::PersistData(time_point tick) +bool CCharEntity::PersistData(timer::time_point tick) { if (tick < nextDataPersistTime || !PersistData()) { @@ -1026,11 +1026,11 @@ bool CCharEntity::PersistData(time_point tick) return true; } -void CCharEntity::Tick(time_point tick) +void CCharEntity::Tick(timer::time_point tick) { TracyZoneScoped; CBattleEntity::Tick(tick); - if (m_DeathTimestamp > 0 && tick >= m_deathSyncTime) + if (m_DeathTimestamp > timer::time_point::min() && tick >= m_deathSyncTime) { // Send an update packet at a regular interval to keep the player's death variables synced updatemask |= UPDATE_STATUS; @@ -1091,7 +1091,7 @@ void CCharEntity::PostTick() m_EffectsChanged = false; } - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + timer::time_point now = timer::now(); if (updatemask && now > m_nextUpdateTimer) { @@ -1271,7 +1271,7 @@ bool CCharEntity::OnAttack(CAttackState& state, action_t& action) { TracyZoneScoped; auto* controller{ static_cast(PAI->GetController()) }; - controller->setLastAttackTime(server_clock::now()); + controller->setLastAttackTime(timer::now()); auto ret = CBattleEntity::OnAttack(state, action); return ret; @@ -1415,7 +1415,7 @@ void CCharEntity::OnCastFinished(CMagicState& state, action_t& action) auto scEffect = PTarget->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN, 0); if (isHelix && scEffect) { - scEffect->SetDuration(scEffect->GetDuration() + 2000); + scEffect->SetDuration(scEffect->GetDuration() + 2s); } } } @@ -1721,17 +1721,22 @@ void CCharEntity::OnAbility(CAbilityState& state, action_t& action) } // get any available merit recast reduction - uint8 meritRecastReduction = 0; + auto meritRecastReduction = 0s; if (PAbility->getMeritModID() > 0 && !(PAbility->getAddType() & ADDTYPE_MERIT)) { - meritRecastReduction = PMeritPoints->GetMeritValue((MERIT_TYPE)PAbility->getMeritModID(), this); + meritRecastReduction = std::chrono::seconds(PMeritPoints->GetMeritValue((MERIT_TYPE)PAbility->getMeritModID(), this)); } auto* charge = ability::GetCharge(this, PAbility->getRecastId()); if (charge && PAbility->getID() != ABILITY_SIC) { - action.recast = charge->chargeTime * PAbility->getRecastTime() - meritRecastReduction; + // TODO: this is bad + // "recast" 1-4 = sic/ready + // "recast" 1 = quickdraw, stratagems + auto crypticRecastSecondsAsType = timer::count_seconds(PAbility->getRecastTime()); + + action.recast = charge->chargeTime * crypticRecastSecondsAsType - meritRecastReduction; } else { @@ -1742,7 +1747,7 @@ void CCharEntity::OnAbility(CAbilityState& state, action_t& action) { if (this->StatusEffectContainer->HasStatusEffect(EFFECT_TABULA_RASA)) { - action.recast = 0; + action.recast = 0s; } } else if (PAbility->getRecastId() == 173 || PAbility->getRecastId() == 174) // BP rage, BP ward @@ -1762,10 +1767,10 @@ void CCharEntity::OnAbility(CAbilityState& state, action_t& action) // Localvar will set the BP ability timer when the move consumes MP // The delay is snapshot when the player uses the ability: https://www.bg-wiki.com/ffxi/Blood_Pact_Ability_Delay - this->SetLocalVar("bpRecastTime", static_cast(std::max(0, action.recast - bloodPactDelayReduction))); + this->SetLocalVar("bpRecastTime", static_cast(timer::count_seconds(std::max(0s, action.recast - std::chrono::seconds(bloodPactDelayReduction))))); // Recast is actually triggered when the bp goes off (no recast packet at all on using a bp and the target moving out of range of the pet) - action.recast = 0; + action.recast = 0s; } // remove invisible if aggressive @@ -1799,12 +1804,12 @@ void CCharEntity::OnAbility(CAbilityState& state, action_t& action) { // TODO: Transform this into an item Mod::REWARD_RECAST perhaps ? // The Bison/Brave's Warbonnet & Khimaira/Stout Bonnet reduces recast time by 10 seconds. - action.recast -= 10; // remove 10 seconds + action.recast -= 10s; // remove 10 seconds } } else if (PAbility->getID() == ABILITY_READY || PAbility->getID() == ABILITY_SIC) { - action.recast = static_cast(std::max(0, action.recast - getMod(Mod::SIC_READY_RECAST))); + action.recast = std::max(0s, action.recast - std::chrono::seconds(getMod(Mod::SIC_READY_RECAST))); } action.id = this->id; @@ -1895,7 +1900,7 @@ void CCharEntity::OnAbility(CAbilityState& state, action_t& action) addMP((int32)-mpCost); if (this->GetLocalVar("bpRecastTime") > 0) // This will go away when all smn petskills are handled via jobutils/summoner.lua { - action.recast = this->GetLocalVar("bpRecastTime"); + action.recast = std::chrono::seconds(this->GetLocalVar("bpRecastTime")); } if (PAbility->getValidTarget() == TARGET_SELF) @@ -2446,15 +2451,15 @@ void CCharEntity::OnRaise() // add weakness effect (75% reduction in HP/MP) if (GetLocalVar("MijinGakure") == 0) { - uint32 weaknessTime = 300; + auto weaknessTime = 5min; // Arise has a reduced weakness time of 3 mins if (m_hasArise) { - weaknessTime = 180; + weaknessTime = 3min; } - CStatusEffect* PWeaknessEffect = new CStatusEffect(EFFECT_WEAKNESS, EFFECT_WEAKNESS, m_weaknessLvl, 0, weaknessTime); + CStatusEffect* PWeaknessEffect = new CStatusEffect(EFFECT_WEAKNESS, EFFECT_WEAKNESS, m_weaknessLvl, 0s, weaknessTime); StatusEffectContainer->AddStatusEffect(PWeaknessEffect); } @@ -2519,7 +2524,7 @@ void CCharEntity::OnRaise() // If Arise was used then apply a reraise 3 effect on the target if (m_hasArise) { - CStatusEffect* PReraiseEffect = new CStatusEffect(EFFECT_RERAISE, EFFECT_RERAISE, 3, 0, 3600); + CStatusEffect* PReraiseEffect = new CStatusEffect(EFFECT_RERAISE, EFFECT_RERAISE, 3, 0s, 1h); StatusEffectContainer->AddStatusEffect(PReraiseEffect); } @@ -2578,7 +2583,7 @@ void CCharEntity::OnItemFinish(CItemState& state, action_t& action) { PItem->setCurrentCharges(PItem->getCurrentCharges() - 1); } - PItem->setLastUseTime(CVanaTime::getInstance()->getVanaTime()); + PItem->setLastUseTime(timer::now()); db::preparedStmt("UPDATE char_inventory " "SET extra = ? " @@ -2587,8 +2592,8 @@ void CCharEntity::OnItemFinish(CItemState& state, action_t& action) if (PItem->getCurrentCharges() != 0) { - this->PRecastContainer->Add(RECAST_ITEM, PItem->getSlotID() << 8 | PItem->getLocationID(), - PItem->getReuseTime() / 1000); // add recast timer to Recast List from any bag + // add recast timer to Recast List from any bag + this->PRecastContainer->Add(RECAST_ITEM, PItem->getSlotID() << 8 | PItem->getLocationID(), PItem->getReuseTime()); } } else // unlock all items except equipment @@ -2657,7 +2662,7 @@ void CCharEntity::Die() } Die(death_duration); - SetDeathTimestamp((uint32)time(nullptr)); + SetDeathTime(timer::now()); setBlockingAid(false); @@ -2675,7 +2680,7 @@ void CCharEntity::Die() luautils::OnPlayerDeath(this); } -void CCharEntity::Die(duration _duration) +void CCharEntity::Die(timer::duration _duration) { TracyZoneScoped; @@ -2694,7 +2699,7 @@ void CCharEntity::Die(duration _duration) m_weaknessLvl = 0; } - m_deathSyncTime = server_clock::now() + death_update_frequency; + m_deathSyncTime = timer::now() + death_update_frequency; PAI->ClearStateStack(); PAI->Internal_Die(_duration); @@ -2732,29 +2737,25 @@ void CCharEntity::Raise() TracyZoneScoped; PAI->Internal_Raise(); - SetDeathTimestamp(0); + SetDeathTime(timer::time_point::min()); } -void CCharEntity::SetDeathTimestamp(uint32 timestamp) +void CCharEntity::SetDeathTime(timer::time_point timestamp) { m_DeathTimestamp = timestamp; } -int32 CCharEntity::GetSecondsElapsedSinceDeath() const +timer::duration CCharEntity::GetTimeSinceDeath() const { - return m_DeathTimestamp > 0 ? (uint32)time(nullptr) - m_DeathTimestamp : 0; + return m_DeathTimestamp > timer::time_point::min() ? timer::now() - m_DeathTimestamp : 0s; } -int32 CCharEntity::GetTimeRemainingUntilDeathHomepoint() const +timer::duration CCharEntity::GetTimeUntilDeathHomepoint() const { - // 0x0003A020 is 60 * 3960 and 3960 is 66 minutes in seconds - // The client uses this time as the maximum amount of time for death - // We convert the elapsed death time to this total time and subtract it which gives us the remaining time to a forced homepoint - // Once the returned value here reaches below 360 then the client with force homepoint the character - return 0x0003A020 - (60 * GetSecondsElapsedSinceDeath()); + return 60min - GetTimeSinceDeath(); } -int32 CCharEntity::GetTimeCreated() +earth_time::time_point CCharEntity::GetTimeCreated() { TracyZoneScoped; @@ -2762,10 +2763,10 @@ int32 CCharEntity::GetTimeCreated() if (rset && rset->rowsCount() && rset->next()) { - return rset->get(0); + return earth_time::time_point(std::chrono::seconds(rset->get("UNIX_TIMESTAMP(timecreated)"))); } - return 0; + return earth_time::time_point::min(); } uint8 CCharEntity::getHighestJobLevel() @@ -3310,12 +3311,11 @@ int32 CCharEntity::getCharVar(std::string const& charVarName) { if (auto charVar = charVarCache.find(charVarName); charVar != charVarCache.end()) { - std::pair cachedVarData = charVar->second; - uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); + std::pair cachedVarData = charVar->second; // If the cached variable is not expired, return it. Else, fall through so that the // database can be cleaned up. - if (cachedVarData.second == 0 || cachedVarData.second > currentTimestamp) + if (cachedVarData.second == 0 || cachedVarData.second > earth_time::timestamp()) { return cachedVarData.first; } @@ -3329,7 +3329,7 @@ int32 CCharEntity::getCharVar(std::string const& charVarName) auto CCharEntity::getCharVarsWithPrefix(std::string const& prefix) -> std::vector> { - const uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); + const auto currentTimestamp = earth_time::timestamp(); std::vector> charVars; diff --git a/src/map/entities/charentity.h b/src/map/entities/charentity.h index 0a4d3110e7c..adc130e04ad 100644 --- a/src/map/entities/charentity.h +++ b/src/map/entities/charentity.h @@ -90,14 +90,14 @@ struct profile_t struct capacityChain_t { - uint16 chainNumber; - uint32 chainTime; + uint16 chainNumber; + timer::time_point chainTime; }; struct expChain_t { - uint16 chainNumber; - uint32 chainTime; + uint16 chainNumber; + timer::time_point chainTime; }; struct telepoint_t @@ -131,15 +131,15 @@ struct teleport_t struct PetInfo_t { - bool respawnPet; // Used for spawning pet on zone - uint32 jugSpawnTime; // Keeps track of original spawn time in seconds since epoch - uint32 jugDuration; // Number of seconds a jug pet should last after its original spawn time - uint8 petID; // ID as in wyvern(48) , carbuncle(8) ect.. - PET_TYPE petType; // Type of pet being transferred - uint8 petLevel; // Level the pet was spawned with - int16 petHP; - int16 petMP; - float petTP; + bool respawnPet; // Used for spawning pet on zone + timer::time_point jugSpawnTime; // Keeps track of original spawn time + timer::duration jugDuration; // Duration a jug pet should last after its original spawn time + uint8 petID; // ID as in wyvern(48) , carbuncle(8) ect.. + PET_TYPE petType; // Type of pet being transferred + uint8 petLevel; // Level the pet was spawned with + int16 petHP; + int16 petMP; + float petTP; }; struct AuctionHistory_t @@ -259,13 +259,14 @@ class CCharEntity : public CBattleEntity SAVE_CONF playerConfig{}; // Various settings such as chat filter, display head flag, new adventurer, autotarget, etc. - uint32 lastOnline{ 0 }; // UTC Unix Timestamp of the last time char zoned or logged out - bool isNewPlayer() const; // Checks if new player bit is unset. - bool isSeekingParty() const; // is seeking party or not - bool isAnon() const; // is /anon - bool isAway() const; // is /away (tells will not go through) - bool isMentor() const; // If player is a mentor or not. - bool hasAutoTargetEnabled() const; // has autotarget enabled + earth_time::time_point lastOnline{}; // UTC time of the last time char zoned or logged out + + bool isNewPlayer() const; // Checks if new player bit is unset. + bool isSeekingParty() const; // is seeking party or not + bool isAnon() const; // is /anon + bool isAway() const; // is /away (tells will not go through) + bool isMentor() const; // If player is a mentor or not. + bool hasAutoTargetEnabled() const; // has autotarget enabled profile_t profile{}; capacityChain_t capacityChain{}; @@ -284,7 +285,7 @@ class CCharEntity : public CBattleEntity uint8 m_TitleList[143]{}; // List of obtained titles uint8 m_Abilities[64]{}; // List of current abilities uint8 m_LearnedAbilities[49]{}; // Learnable abilities (corsair rolls) - xi::bitset<64> m_LearnedWeaponskills; // Learnable Weaponskills + xi::bitset<64> m_LearnedWeaponskills{}; // Learnable Weaponskills uint8 m_TraitList[18]{}; // List of active job traits in the form of a bit mask uint8 m_PetCommands[64]{}; uint8 m_WeaponSkills[32]{}; @@ -451,20 +452,20 @@ class CCharEntity : public CBattleEntity void SetName(const std::string& name); // set the name of character, limited to 15 characters - time_point lastTradeInvite{}; - EntityID_t TradePending{}; // Character ID offering trade - EntityID_t InvitePending{}; // Character ID sending party invite - EntityID_t BazaarID{}; // Pointer to the bazaar we are browsing. - BazaarList_t BazaarCustomers{}; // Array holding the IDs of the current customers + timer::time_point lastTradeInvite{}; + EntityID_t TradePending{}; // Character ID offering trade + EntityID_t InvitePending{}; // Character ID sending party invite + EntityID_t BazaarID{}; // Pointer to the bazaar we are browsing. + BazaarList_t BazaarCustomers{}; // Array holding the IDs of the current customers std::unique_ptr m_PMonstrosity; - uint8 m_LevelRestriction; // Character level limit - uint16 m_Costume; - uint16 m_Costume2; - uint32 m_AHHistoryTimestamp; - uint32 m_DeathTimestamp; - time_point m_deathSyncTime{}; // Timer used for sending an update packet at a regular interval while the character is dead + uint8 m_LevelRestriction; // Character level limit + uint16 m_Costume; + uint16 m_Costume2; + timer::time_point m_AHHistoryTimestamp; + timer::time_point m_DeathTimestamp; + timer::time_point m_deathSyncTime{}; // Timer used for sending an update packet at a regular interval while the character is dead uint8 m_hasTractor; // checks if player has tractor already uint8 m_hasRaise; // checks if player has raise already @@ -475,10 +476,10 @@ class CCharEntity : public CBattleEntity location_t m_previousLocation{}; - uint32 m_PlayTime; - uint32 m_SaveTime; + timer::duration m_PlayTime; + timer::time_point m_SaveTime; - time_point m_LeaderCreatedPartyTime{}; // Time that a party member joined and this player was leader. + timer::time_point m_LeaderCreatedPartyTime{}; // Time that a party member joined and this player was leader. uint8 m_GMlevel; // Level of the GM flag assigned to this character bool m_isGMHidden; // GM Hidden flag to prevent player updates from being processed. @@ -502,10 +503,10 @@ class CCharEntity : public CBattleEntity // Send updates about dirty containers in post tick std::map dirtyInventoryContainers; - bool m_EquipSwap; // true if equipment was recently changed - bool m_EffectsChanged; - time_point m_LastSynthTime{}; - time_point m_LastRangedAttackTime{}; + bool m_EquipSwap; // true if equipment was recently changed + bool m_EffectsChanged; + timer::time_point m_LastSynthTime{}; + timer::time_point m_LastRangedAttackTime{}; CHAR_SUBSTATE m_Substate; @@ -516,11 +517,11 @@ class CCharEntity : public CBattleEntity std::vector m_GearSetMods; // The list of gear set mods currently applied to the character. std::vector m_ah_history; // AH history list (in the future consider using UContainer) - std::unordered_map m_PacketRecievedTimestamps; - uint16 m_LastPacketType{}; + std::unordered_map m_PacketRecievedTimestamps; + uint16 m_LastPacketType{}; - void SetPlayTime(uint32 playTime); // Set playtime - uint32 GetPlayTime(bool needUpdate = true); // Get playtime + void SetPlayTime(timer::duration playTime); // Set playtime + timer::duration GetPlayTime(bool needUpdate = true); // Get playtime CItemEquipment* getEquip(SLOTTYPE slot); @@ -540,9 +541,9 @@ class CCharEntity : public CBattleEntity void RequestPersist(CHAR_PERSIST toPersist); bool PersistData(); - bool PersistData(time_point tick); + bool PersistData(timer::time_point tick); - virtual void Tick(time_point) override; + virtual void Tick(timer::time_point) override; void PostTick() override; virtual void addTrait(CTrait*) override; @@ -553,17 +554,18 @@ class CCharEntity : public CBattleEntity bool IsMobOwner(CBattleEntity* PTarget); virtual void Die() override; - void Die(duration _duration); + void Die(timer::duration _duration); void Raise(); - static constexpr duration death_duration = 60min; - static constexpr duration death_update_frequency = 16s; + static constexpr timer::duration death_duration = 60min; + static constexpr timer::duration death_update_frequency = 16s; + + void SetDeathTime(timer::time_point timestamp); + timer::duration GetTimeSinceDeath() const; + timer::duration GetTimeUntilDeathHomepoint() const; - void SetDeathTimestamp(uint32 timestamp); - int32 GetSecondsElapsedSinceDeath() const; - int32 GetTimeRemainingUntilDeathHomepoint() const; + earth_time::time_point GetTimeCreated(); - int32 GetTimeCreated(); uint8 getHighestJobLevel(); bool isInTriggerArea(uint32 triggerAreaId); @@ -650,8 +652,8 @@ class CCharEntity : public CBattleEntity std::unordered_set charVarChanges; std::unordered_set charTriggerAreaIDs; // Holds any TriggerArea IDs that the player is currently within the bounds of - uint8 dataToPersist = 0; - time_point nextDataPersistTime{}; + uint8 dataToPersist = 0; + timer::time_point nextDataPersistTime{}; // TODO: Don't use raw ptrs for this, but don't duplicate whole packets with unique_ptr either. std::deque> PacketList; // The list of packets to be sent to the character during the next network cycle diff --git a/src/map/entities/mobentity.cpp b/src/map/entities/mobentity.cpp index 00914f8cf18..32b5bbda96e 100644 --- a/src/map/entities/mobentity.cpp +++ b/src/map/entities/mobentity.cpp @@ -85,14 +85,14 @@ namespace }; // clang-format on - constexpr int RECAST_SEAL = 1; - constexpr int RECAST_GEODE = 2; - constexpr int SPECIAL_DROP_COOLDOWN = 300; // 5 minutes between special drops + constexpr int RECAST_SEAL = 1; + constexpr int RECAST_GEODE = 2; + constexpr timer::duration SPECIAL_DROP_COOLDOWN = 5min; // 5 minutes between special drops } // namespace CMobEntity::CMobEntity() : m_AllowRespawn(false) -, m_RespawnTime(300) +, m_RespawnTime(5min) , m_DropItemTime(0) , m_DropID(0) , m_minLevel(1) @@ -203,20 +203,20 @@ void CMobEntity::setEntityFlags(uint32 EntityFlags) * * ************************************************************************/ -time_point CMobEntity::GetDespawnTime() +timer::time_point CMobEntity::GetDespawnTime() { return m_DespawnTimer; } -void CMobEntity::SetDespawnTime(duration _duration) +void CMobEntity::SetDespawnTime(timer::duration _duration) { if (_duration > 0s) { - m_DespawnTimer = server_clock::now() + _duration; + m_DespawnTimer = timer::now() + _duration; } else { - m_DespawnTimer = time_point::min(); + m_DespawnTimer = timer::time_point::min(); } } @@ -529,7 +529,7 @@ void CMobEntity::PostTick() { TracyZoneScoped; CBattleEntity::PostTick(); - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + timer::time_point now = timer::now(); if (loc.zone && updatemask && now > m_nextUpdateTimer) { m_nextUpdateTimer = now + 250ms; @@ -600,7 +600,7 @@ void CMobEntity::Spawn() m_THLvl = 0; m_ItemStolen = false; m_ItemDespoiled = false; - m_DropItemTime = 1000; + m_DropItemTime = 1000ms; animationsub = (uint8)getMobMod(MOBMOD_SPAWN_ANIMATIONSUB); SetCallForHelpFlag(false); @@ -641,7 +641,7 @@ void CMobEntity::Spawn() } } - m_DespawnTimer = time_point::min(); + m_DespawnTimer = timer::time_point::min(); luautils::OnMobSpawn(this); } @@ -1143,7 +1143,7 @@ void CMobEntity::OnDespawn(CDespawnState& /*unused*/) { TracyZoneScoped; FadeOut(); - PAI->Internal_Respawn(std::chrono::milliseconds(m_RespawnTime)); + PAI->Internal_Respawn(m_RespawnTime); luautils::OnMobDespawn(this); // #event despawn PAI->EventHandler.triggerListener("DESPAWN", this); @@ -1168,7 +1168,7 @@ void CMobEntity::Die() CBattleEntity::Die(); // clang-format off - PAI->QueueAction(queueAction_t(std::chrono::milliseconds(m_DropItemTime), false, [this](CBaseEntity* PEntity) + PAI->QueueAction(queueAction_t(m_DropItemTime, false, [this](CBaseEntity* PEntity) { if (static_cast(PEntity)->isDead()) { diff --git a/src/map/entities/mobentity.h b/src/map/entities/mobentity.h index 2111f9079ba..7ec94b0bcdc 100644 --- a/src/map/entities/mobentity.h +++ b/src/map/entities/mobentity.h @@ -125,13 +125,13 @@ class CMobEntity : public CBattleEntity uint16 TPUseChance(); // return % chance to use TP move per 400ms tick - bool CanDeaggro() const; - time_point GetDespawnTime(); - void SetDespawnTime(duration _duration); - uint32 GetRandomGil(); // returns a random amount of gil - bool CanRoamHome(); // is it possible for me to walk back? - bool CanRoam(); // check if mob can walk around - void TapDeaggroTime(); // call CMobController->TapDeaggroTime if PAI->GetController() is a CMobController, otherwise do nothing. + bool CanDeaggro() const; + timer::time_point GetDespawnTime(); + void SetDespawnTime(timer::duration _duration); + uint32 GetRandomGil(); // returns a random amount of gil + bool CanRoamHome(); // is it possible for me to walk back? + bool CanRoam(); // check if mob can walk around + void TapDeaggroTime(); // call CMobController->TapDeaggroTime if PAI->GetController() is a CMobController, otherwise do nothing. bool CanLink(position_t* pos, int16 superLink = 0); @@ -185,9 +185,9 @@ class CMobEntity : public CBattleEntity virtual void FadeOut() override; virtual bool isWideScannable() override; - bool m_AllowRespawn; // if true, allow respawn - uint32 m_RespawnTime; // respawn time - uint32 m_DropItemTime; // time until monster death animation + bool m_AllowRespawn; // if true, allow respawn + timer::duration m_RespawnTime; // respawn time + timer::duration m_DropItemTime; // time until monster death animation uint32 m_DropID; // dropid of items to be dropped. dropid in Database (mob_droplist) @@ -275,7 +275,7 @@ class CMobEntity : public CBattleEntity void DropItems(CCharEntity* PChar); private: - time_point m_DespawnTimer{ time_point::min() }; // Despawn Timer to despawn mob after set duration + timer::time_point m_DespawnTimer{ timer::time_point::min() }; // Despawn Timer to despawn mob after set duration std::unordered_map m_mobModStat; std::unordered_map m_mobModStatSave; static constexpr float roam_home_distance{ 60.f }; diff --git a/src/map/entities/npcentity.cpp b/src/map/entities/npcentity.cpp index 6a826f9dca4..a06616e3be3 100644 --- a/src/map/entities/npcentity.cpp +++ b/src/map/entities/npcentity.cpp @@ -109,7 +109,7 @@ bool CNpcEntity::isWideScannable() void CNpcEntity::PostTick() { - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + timer::time_point now = timer::now(); if (loc.zone && updatemask && status != STATUS_TYPE::DISAPPEAR && now > m_nextUpdateTimer) { m_nextUpdateTimer = now + 250ms; diff --git a/src/map/entities/npcentity.h b/src/map/entities/npcentity.h index a257eb14f76..062a699ae2b 100644 --- a/src/map/entities/npcentity.h +++ b/src/map/entities/npcentity.h @@ -43,7 +43,7 @@ class CNpcEntity : public CBaseEntity bool IsTriggerable() const; virtual bool isWideScannable() override; virtual void PostTick() override; - virtual void Tick(time_point) override + virtual void Tick(timer::time_point) override { } diff --git a/src/map/entities/petentity.cpp b/src/map/entities/petentity.cpp index f79fe0aaf16..fb85d967f69 100644 --- a/src/map/entities/petentity.cpp +++ b/src/map/entities/petentity.cpp @@ -37,6 +37,7 @@ #include "utils/mobutils.h" #include "utils/petutils.h" +#include "common/timer.h" #include "common/utils.h" #include "petentity.h" @@ -45,8 +46,8 @@ CPetEntity::CPetEntity(PET_TYPE petType) , m_PetID(0) , m_PetType(petType) , m_spawnLevel(0) -, m_jugSpawnTime(time_point::min()) -, m_jugDuration(duration::min()) +, m_jugSpawnTime(timer::time_point::min()) +, m_jugDuration(timer::duration::min()) { TracyZoneScoped; objtype = TYPE_PET; @@ -84,19 +85,17 @@ bool CPetEntity::isBstPet() return getPetType() == PET_TYPE::JUG_PET || objtype == TYPE_MOB; } -uint32 CPetEntity::getJugSpawnTime() +timer::time_point CPetEntity::getJugSpawnTime() { if (m_PetType != PET_TYPE::JUG_PET) { ShowWarning("Non-Jug Pet calling function (%d).", static_cast(m_PetType)); - return 0; } - const auto epoch = m_jugSpawnTime.time_since_epoch(); - return static_cast(std::chrono::duration_cast(epoch).count()); + return m_jugSpawnTime; } -void CPetEntity::setJugSpawnTime(uint32 spawnTime) +void CPetEntity::setJugSpawnTime(timer::time_point spawnTime) { if (m_PetType != PET_TYPE::JUG_PET) { @@ -104,21 +103,21 @@ void CPetEntity::setJugSpawnTime(uint32 spawnTime) return; } - m_jugSpawnTime = std::chrono::system_clock::time_point(std::chrono::duration(spawnTime)); + m_jugSpawnTime = spawnTime; } -uint32 CPetEntity::getJugDuration() +timer::duration CPetEntity::getJugDuration() { if (m_PetType != PET_TYPE::JUG_PET) { ShowWarning("Non-Jug Pet calling function (%d).", static_cast(m_PetType)); - return 0; + return 0s; } - return static_cast(std::chrono::duration_cast(m_jugDuration).count()); + return m_jugDuration; } -void CPetEntity::setJugDuration(uint32 seconds) +void CPetEntity::setJugDuration(timer::duration seconds) { if (m_PetType != PET_TYPE::JUG_PET) { @@ -126,7 +125,7 @@ void CPetEntity::setJugDuration(uint32 seconds) return; } - m_jugDuration = std::chrono::seconds(seconds); + m_jugDuration = seconds; } const std::string CPetEntity::GetScriptName() @@ -204,7 +203,7 @@ WYVERN_TYPE CPetEntity::getWyvernType() void CPetEntity::PostTick() { CBattleEntity::PostTick(); - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + timer::time_point now = timer::now(); if (loc.zone && updatemask && status != STATUS_TYPE::DISAPPEAR && now > m_nextUpdateTimer) { m_nextUpdateTimer = now + 250ms; @@ -262,7 +261,7 @@ void CPetEntity::Spawn() if (m_PetType == PET_TYPE::JUG_PET) { - m_jugSpawnTime = server_clock::now(); + m_jugSpawnTime = timer::now(); } // NOTE: This is purposefully calling CBattleEntity's impl. diff --git a/src/map/entities/petentity.h b/src/map/entities/petentity.h index ae9763736cb..5e43a90f72f 100644 --- a/src/map/entities/petentity.h +++ b/src/map/entities/petentity.h @@ -55,9 +55,9 @@ class CPetEntity : public CMobEntity PET_TYPE getPetType(); uint8 getSpawnLevel(); void setSpawnLevel(uint8 level); - uint32 getJugSpawnTime(); // initial spawn time (in seconds since epoch) of this pet if it's a jug pet - uint32 getJugDuration(); // duration of this jug pet in seconds - void setJugDuration(uint32 seconds); // sets the duration of this jug pet in seconds + timer::time_point getJugSpawnTime(); // initial spawn time of this pet if it's a jug pet + timer::duration getJugDuration(); // duration of this jug pet in seconds + void setJugDuration(timer::duration seconds); // sets the duration of this jug pet in seconds bool isBstPet(); uint32 m_PetID; const std::string GetScriptName(); @@ -74,12 +74,12 @@ class CPetEntity : public CMobEntity virtual bool CanAttack(CBattleEntity* PTarget, std::unique_ptr& errMsg) override; private: - PET_TYPE m_PetType; // the type of pet e.g. avatar/wyvern/jugpet etc - uint8 m_spawnLevel; // The level the pet was spawned at - time_point m_jugSpawnTime; // original spawn time of a jug pet - duration m_jugDuration; // Time before the jug is despawned after being called + PET_TYPE m_PetType; // the type of pet e.g. avatar/wyvern/jugpet etc + uint8 m_spawnLevel; // The level the pet was spawned at + timer::time_point m_jugSpawnTime; // original spawn time of a jug pet + timer::duration m_jugDuration; // Time before the jug is despawned after being called - void setJugSpawnTime(uint32 spawnTime); // sets the initial spawn time of this pet in seconds since epoch + void setJugSpawnTime(timer::time_point spawnTime); // sets the initial spawn time of this pet }; #endif diff --git a/src/map/entities/trustentity.cpp b/src/map/entities/trustentity.cpp index 1478dc25f08..67e048be1a3 100644 --- a/src/map/entities/trustentity.cpp +++ b/src/map/entities/trustentity.cpp @@ -69,7 +69,7 @@ void CTrustEntity::PostTick() // NOTE: This is purposefully calling CBattleEntity's impl. // TODO: Calling a grand-parent's impl. of an overridden function is bad CBattleEntity::PostTick(); - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + timer::time_point now = timer::now(); if (loc.zone && updatemask && status != STATUS_TYPE::DISAPPEAR && now > m_nextUpdateTimer) { m_nextUpdateTimer = now + 250ms; diff --git a/src/map/fishingcontest.cpp b/src/map/fishingcontest.cpp index 3914226762d..69ce902287e 100644 --- a/src/map/fishingcontest.cpp +++ b/src/map/fishingcontest.cpp @@ -125,7 +125,7 @@ namespace fishingcontest return; } - uint32 currentTime = CVanaTime::getInstance()->getSysTime(); + uint32 currentTime = earth_time::timestamp(); if (currentTime > CurrentFishingContest.changeTime) { FISHING_CONTEST_STATUS newStatus = static_cast((static_cast(CurrentFishingContest.status) + 1) % static_cast(FISHING_CONTEST_STATUS::CLOSED)); @@ -490,7 +490,7 @@ namespace fishingcontest entry.allegiance = (uint8)PChar->allegiance; entry.fishRank = PChar->RealSkills.rank[SKILLTYPE::SKILL_FISHING]; entry.score = score; - entry.submitTime = CVanaTime::getInstance()->getVanaTime(); + entry.submitTime = earth_time::vanadiel_timestamp(); entry.contestRank = 0; entry.share = 0; entry.dataset_b = 0; @@ -653,7 +653,7 @@ namespace fishingcontest SetContestFish(fishId); SetContestCriteria(criteria); SetContestMeasure(measure); - SetContestStartTime(CVanaTime::getInstance()->getSysTime()); + SetContestStartTime(earth_time::timestamp()); SetContestChangeTime(GetStageChangeTime(FISHING_CONTEST_STATUS::CONTESTING, CurrentFishingContest.startTime)); SetContestStatus(FISHING_CONTEST_STATUS::CONTESTING); diff --git a/src/map/guild.cpp b/src/map/guild.cpp index c8203e91e71..b80d218f9f9 100644 --- a/src/map/guild.cpp +++ b/src/map/guild.cpp @@ -29,9 +29,12 @@ CGuild::CGuild(uint8 id, const std::string& _pointsName) : m_id(id) { + earth_time::duration currentTime = std::chrono::seconds(earth_time::vanadiel_timestamp()) - 24h; + uint32 elapsedDays = std::chrono::floor(currentTime).count(); + for (size_t i = 0; i < m_GPItemsRank.size(); ++i) { - m_GPItemsRank[i] = (uint8)((CVanaTime::getInstance()->getVanaTime() / (60 * 60 * 24)) % (i + 4)); + m_GPItemsRank[i] = static_cast(elapsedDays % (i + 4)); } pointsName = _pointsName; diff --git a/src/map/guild.h b/src/map/guild.h index b1d2ce8051d..4b101481be0 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -42,7 +42,7 @@ struct GPItem_t GPItem_t(CItem* _item, uint16 _maxpoints, uint16 _points) : item(_item) , maxpoints(_maxpoints) - , points(_points) {}; + , points(_points){}; }; class CGuild diff --git a/src/map/instance.cpp b/src/map/instance.cpp index 08f64066b6f..acd804ed175 100644 --- a/src/map/instance.cpp +++ b/src/map/instance.cpp @@ -38,7 +38,7 @@ CInstance::CInstance(CZone* zone, uint32 instanceid) TracyZoneScoped; LoadInstance(); - m_startTime = server_clock::now(); + m_startTime = timer::now(); m_wipeTimer = m_startTime; } @@ -148,27 +148,27 @@ position_t CInstance::GetEntryLoc() return m_entryloc; } -duration CInstance::GetTimeLimit() +timer::duration CInstance::GetTimeLimit() { return m_timeLimit; } -void CInstance::SetTimeLimit(duration time) +void CInstance::SetTimeLimit(timer::duration time) { m_timeLimit = time; } -duration CInstance::GetLastTimeUpdate() +timer::duration CInstance::GetLastTimeUpdate() { return m_lastTimeUpdate; } -duration CInstance::GetWipeTime() +timer::duration CInstance::GetWipeTime() { return m_wipeTimer - m_startTime; } -duration CInstance::GetElapsedTime(time_point tick) +timer::duration CInstance::GetElapsedTime(timer::time_point tick) { return tick - m_startTime; } @@ -192,7 +192,7 @@ void CInstance::SetEntryLoc(float x, float y, float z, float rot) m_entryloc.rotation = (uint8)rot; } -void CInstance::SetLastTimeUpdate(duration lastTime) +void CInstance::SetLastTimeUpdate(timer::duration lastTime) { m_lastTimeUpdate = lastTime; } @@ -208,7 +208,7 @@ void CInstance::SetStage(uint32 stage) m_stage = stage; } -void CInstance::SetWipeTime(duration time) +void CInstance::SetWipeTime(timer::duration time) { m_wipeTimer = time + m_startTime; } @@ -224,11 +224,11 @@ void CInstance::SetLocalVar(std::string const& name, uint64_t value) * * ************************************************************************/ -void CInstance::CheckTime(time_point tick) +void CInstance::CheckTime(timer::time_point tick) { if (m_lastTimeCheck + 1s <= tick && !Failed()) { - luautils::OnInstanceTimeUpdate(GetZone(), this, (uint32)std::chrono::duration_cast(GetElapsedTime(tick)).count()); + luautils::OnInstanceTimeUpdate(GetZone(), this, static_cast(timer::count_milliseconds(GetElapsedTime(tick)))); m_lastTimeCheck = tick; } } diff --git a/src/map/instance.h b/src/map/instance.h index 59404de8c06..5d5a5658dba 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -45,25 +45,25 @@ class CInstance : public CZoneEntities uint16 GetID() const; uint8 GetLevelCap() const; const std::string& GetName(); - position_t GetEntryLoc(); // Get entry location - duration GetTimeLimit(); // Get instance time limit - duration GetLastTimeUpdate(); // Get last time a "Time Remaining:" message was displayed - uint32 GetProgress() const; // Tracks the progress through the current stage - uint32 GetStage() const; // Tracks the progress through the instance (eg. floor #) - duration GetWipeTime(); // Get time wipe happened (elapsed since start) - duration GetElapsedTime(time_point tick); // Get elapsed time so far + position_t GetEntryLoc(); // Get entry location + timer::duration GetTimeLimit(); // Get instance time limit + timer::duration GetLastTimeUpdate(); // Get last time a "Time Remaining:" message was displayed + uint32 GetProgress() const; // Tracks the progress through the current stage + uint32 GetStage() const; // Tracks the progress through the instance (eg. floor #) + timer::duration GetWipeTime(); // Get time wipe happened (elapsed since start) + timer::duration GetElapsedTime(timer::time_point tick); // Get elapsed time so far uint64_t GetLocalVar(std::string const& name) const; void SetLevelCap(uint8 cap); void SetEntryLoc(float x, float y, float z, float rot); // Set entry location - void SetLastTimeUpdate(duration time); // Set last time a "Time Remaining:" message was displayed - void SetTimeLimit(duration time); // Set instance time limit + void SetLastTimeUpdate(timer::duration time); // Set last time a "Time Remaining:" message was displayed + void SetTimeLimit(timer::duration time); // Set instance time limit void SetProgress(uint32 progress); // Set progress through current stage void SetStage(uint32 stage); // Set current stage (eg. floor #) - void SetWipeTime(duration time); // Set elapsed time when a wipe is detected + void SetWipeTime(timer::duration time); // Set elapsed time when a wipe is detected void SetLocalVar(std::string const& name, uint64_t value); - void CheckTime(time_point tick); // Check time limit (run instance time script) + void CheckTime(timer::time_point tick); // Check time limit (run instance time script) bool CharRegistered(CCharEntity* PChar); // Check if PChar is registered to this instance void ClearEntities(); void Fail(); // Fails the instance (onInstanceFailure) @@ -87,11 +87,11 @@ class CInstance : public CZoneEntities CZone* m_zone; uint32 m_commander{ 0 }; uint8 m_levelcap{ 0 }; - duration m_timeLimit{ duration::zero() }; - time_point m_startTime; - duration m_lastTimeUpdate{ duration::zero() }; - time_point m_lastTimeCheck; - time_point m_wipeTimer; + timer::duration m_timeLimit{ timer::duration::zero() }; + timer::time_point m_startTime; + timer::duration m_lastTimeUpdate{ timer::duration::zero() }; + timer::time_point m_lastTimeCheck; + timer::time_point m_wipeTimer; uint32 m_progress{ 0 }; uint32 m_stage{ 0 }; position_t m_entryloc{}; diff --git a/src/map/instance_loader.cpp b/src/map/instance_loader.cpp index 65b02e952e6..c61d68b45d1 100644 --- a/src/map/instance_loader.cpp +++ b/src/map/instance_loader.cpp @@ -106,7 +106,7 @@ CInstance* CInstanceLoader::LoadInstance() PMob->m_SpawnPoint.z = _sql->GetFloatData(5); PMob->loc.p = PMob->m_SpawnPoint; - PMob->m_RespawnTime = _sql->GetUIntData(6) * 1000; + PMob->m_RespawnTime = std::chrono::seconds(_sql->GetUIntData(6)); PMob->m_SpawnType = (SPAWNTYPE)_sql->GetUIntData(7); PMob->m_DropID = _sql->GetUIntData(8); diff --git a/src/map/item_container.cpp b/src/map/item_container.cpp index 9645db0d9c0..c40bf3c46a1 100644 --- a/src/map/item_container.cpp +++ b/src/map/item_container.cpp @@ -28,7 +28,7 @@ CItemContainer::CItemContainer(uint16 LocationID) : SortingPacket(0) -, LastSortingTime(0) +, LastSortingTime(timer::time_point::min()) , m_id(LocationID) , m_buff(0) , m_size(0) diff --git a/src/map/item_container.h b/src/map/item_container.h index 53a123e1eca..7425d3f8742 100644 --- a/src/map/item_container.h +++ b/src/map/item_container.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/logging.h" +#include "common/timer.h" enum CONTAINER_ID : uint8 { @@ -73,8 +74,8 @@ class CItemContainer uint8 InsertItem(CItem* PItem); // add a pre-created item to a free cell uint8 InsertItem(CItem* PItem, uint8 slotID); // add a pre-created item to the selected cell - uint32 SortingPacket; // number of sort requests per clock - uint32 LastSortingTime; + uint32 SortingPacket; // number of sort requests per clock + timer::time_point LastSortingTime; CItem* GetItem(uint8 slotID); // get a pointer to the object located in the specified cell. void Clear(); // remove all items from container diff --git a/src/map/items.h b/src/map/items.h index e6b1682345c..21bf3b71d34 100644 --- a/src/map/items.h +++ b/src/map/items.h @@ -40,6 +40,7 @@ enum ITEMID : uint16 SAIRUI_RAN = 1188, KODOKU = 1191, SHINOBI_TABI = 1194, + SOUL_PLATE = 2477, SANJAKU_TENUGUI = 2553, SOSHI = 2555, KABENRO = 2642, diff --git a/src/map/items/item.cpp b/src/map/items/item.cpp index 035401de95a..cc403d86dbb 100644 --- a/src/map/items/item.cpp +++ b/src/map/items/item.cpp @@ -378,13 +378,15 @@ bool CItem::isSoultrapper() const return m_id == 18721 || m_id == 18724; } -void CItem::setSoulPlateData(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp) +void CItem::setSoulPlateData(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp) { PackSoultrapperName(name, m_extra); - // Hack: Artificially chop off extremely long names, so we can pack the mobFamily info into m_extra - m_extra[17] = (mobFamily & 0xFF00) >> 8; - m_extra[18] = mobFamily & 0x00FF; + // interestData is zone ID (high) + mob family ID (low) + m_extra[15] = (interestData >> 24) & 0xFF; + m_extra[16] = (interestData >> 16) & 0xFF; + m_extra[17] = (interestData >> 8) & 0xFF; + m_extra[18] = interestData & 0xFF; m_extra[19] = zeni; @@ -396,14 +398,17 @@ void CItem::setSoulPlateData(std::string const& name, uint16 mobFamily, uint8 ze m_extra[23] = (0x03 << 4) & fp; } -auto CItem::getSoulPlateData() -> std::tuple +auto CItem::getSoulPlateData() -> std::tuple { - auto name = UnpackSoultrapperName(m_extra); - uint16 mobFamily = (m_extra[17] << 8) + m_extra[18]; + auto name = UnpackSoultrapperName(m_extra); + uint32 interestData = (m_extra[15] << 24) | + (m_extra[16] << 16) | + (m_extra[17] << 8) | + m_extra[18]; uint8 zeni = m_extra[19]; uint16 skillIndex = (m_extra[20] >> 7) + (m_extra[21] << 1) + ((m_extra[22] & 0x03) << 9); uint8 fp = (m_extra[22] >> 3) + ((m_extra[23] & 0x03) << 4); - return std::tuple(name, mobFamily, zeni, skillIndex, fp); + return std::tuple(name, interestData, zeni, skillIndex, fp); } bool CItem::isMannequin() const diff --git a/src/map/items/item.h b/src/map/items/item.h index 376e08e3312..ea6971ca277 100644 --- a/src/map/items/item.h +++ b/src/map/items/item.h @@ -122,8 +122,8 @@ class CItem virtual void setSignature(std::string const& signature); bool isSoultrapper() const; - void setSoulPlateData(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp); - auto getSoulPlateData() -> std::tuple; + void setSoulPlateData(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp); + auto getSoulPlateData() -> std::tuple; bool isMannequin() const; diff --git a/src/map/items/item_usable.cpp b/src/map/items/item_usable.cpp index 50de1d1430e..b79747d9f1c 100644 --- a/src/map/items/item_usable.cpp +++ b/src/map/items/item_usable.cpp @@ -28,53 +28,55 @@ CItemUsable::CItemUsable(uint16 id) : CItem(id) +, m_UseDelay(0s) +, m_AnimationTime(0s) +, m_ActivationTime(0s) +, m_ReuseDelay(0s) { setType(ITEM_USABLE); - m_UseDelay = 0; - m_MaxCharges = 0; - m_Animation = 0; - m_AnimationTime = 0; - m_ActivationTime = 0; - m_ValidTarget = 0; - m_ReuseDelay = 0; - m_AssignTime = 0; - m_AoE = 0; + m_MaxCharges = 0; + m_Animation = 0; + m_ValidTarget = 0; + m_AssignTime = timer::time_point::min(); + m_LastUseTime = timer::time_point::min(); + m_AoE = 0; } CItemUsable::~CItemUsable() = default; -void CItemUsable::setUseDelay(uint8 UseDelay) +void CItemUsable::setUseDelay(timer::duration UseDelay) { m_UseDelay = UseDelay; } -uint8 CItemUsable::getUseDelay() const +timer::duration CItemUsable::getUseDelay() const { return m_UseDelay; } -void CItemUsable::setReuseDelay(uint32 ReuseDelay) +void CItemUsable::setReuseDelay(timer::duration ReuseDelay) { m_ReuseDelay = ReuseDelay; } -uint32 CItemUsable::getReuseDelay() const +timer::duration CItemUsable::getReuseDelay() const { return m_ReuseDelay; } -void CItemUsable::setLastUseTime(uint32 LastUseTime) +void CItemUsable::setLastUseTime(timer::time_point LastUseTime) { - ref(m_extra, 0x04) = LastUseTime; + m_LastUseTime = LastUseTime; + ref(m_extra, 0x04) = earth_time::vanadiel_timestamp(timer::to_utc(LastUseTime)); } -uint32 CItemUsable::getLastUseTime() +timer::time_point CItemUsable::getLastUseTime() { - return ref(m_extra, 0x04); + return m_LastUseTime; } -uint32 CItemUsable::getNextUseTime() +timer::time_point CItemUsable::getNextUseTime() { return getLastUseTime() + m_ReuseDelay; } @@ -109,22 +111,22 @@ uint16 CItemUsable::getAnimationID() const return m_Animation; } -void CItemUsable::setAnimationTime(uint16 AnimationTime) +void CItemUsable::setAnimationTime(timer::duration AnimationTime) { m_AnimationTime = AnimationTime; } -uint16 CItemUsable::getAnimationTime() const +timer::duration CItemUsable::getAnimationTime() const { return m_AnimationTime; } -void CItemUsable::setActivationTime(uint16 ActivationTime) +void CItemUsable::setActivationTime(timer::duration ActivationTime) { m_ActivationTime = ActivationTime; } -uint16 CItemUsable::getActivationTime() const +timer::duration CItemUsable::getActivationTime() const { return m_ActivationTime; } @@ -149,15 +151,15 @@ void CItemUsable::setAoE(uint16 AoE) m_AoE = AoE; } -void CItemUsable::setAssignTime(uint32 VanaTime) +void CItemUsable::setAssignTime(timer::time_point time) { - m_AssignTime = VanaTime; + m_AssignTime = time; } -uint32 CItemUsable::getReuseTime() +timer::duration CItemUsable::getReuseTime() { - uint32 CurrentTime = CVanaTime::getInstance()->getVanaTime(); - uint32 ReuseTime = std::max(m_AssignTime + m_UseDelay, getLastUseTime() + m_ReuseDelay); + timer::time_point CurrentTime = timer::now(); + auto ReuseTime = std::max(m_AssignTime + m_UseDelay, getLastUseTime() + m_ReuseDelay); - return (ReuseTime > CurrentTime ? (ReuseTime - CurrentTime) * 1000 : 0); + return (ReuseTime > CurrentTime ? ReuseTime - CurrentTime : 0s); } diff --git a/src/map/items/item_usable.h b/src/map/items/item_usable.h index f32c213ff1a..c3c68c68362 100644 --- a/src/map/items/item_usable.h +++ b/src/map/items/item_usable.h @@ -32,41 +32,42 @@ class CItemUsable : public CItem CItemUsable(uint16); virtual ~CItemUsable(); - uint8 getUseDelay() const; - uint8 getCurrentCharges(); - uint8 getMaxCharges() const; - uint16 getAnimationID() const; - uint16 getAnimationTime() const; - uint16 getActivationTime() const; - uint16 getValidTarget() const; - uint32 getReuseTime(); - uint32 getReuseDelay() const; - uint32 getLastUseTime(); - uint32 getNextUseTime(); - uint16 getAoE() const; + timer::duration getUseDelay() const; + uint8 getCurrentCharges(); + uint8 getMaxCharges() const; + uint16 getAnimationID() const; + timer::duration getAnimationTime() const; + timer::duration getActivationTime() const; + uint16 getValidTarget() const; + timer::duration getReuseTime(); + timer::duration getReuseDelay() const; + timer::time_point getLastUseTime(); + timer::time_point getNextUseTime(); + uint16 getAoE() const; - void setUseDelay(uint8 UseDelay); + void setUseDelay(timer::duration UseDelay); void setCurrentCharges(uint8 CurrCharges); void setMaxCharges(uint8 MaxCharges); void setAnimationID(uint16 Animation); - void setAnimationTime(uint16 AnimationTime); - void setActivationTime(uint16 ActivationTime); + void setAnimationTime(timer::duration AnimationTime); + void setActivationTime(timer::duration ActivationTime); void setValidTarget(uint16 ValidTarget); - void setReuseDelay(uint32 ReuseDelay); - void setLastUseTime(uint32 LastUseTime); - void setAssignTime(uint32 VanaTime); + void setReuseDelay(timer::duration ReuseDelay); + void setLastUseTime(timer::time_point LastUseTime); + void setAssignTime(timer::time_point VanaTime); void setAoE(uint16 AoE); private: - uint8 m_UseDelay; - uint8 m_MaxCharges; - uint16 m_Animation; - uint16 m_AnimationTime; - uint16 m_ActivationTime; - uint16 m_ValidTarget; - uint32 m_ReuseDelay; - uint32 m_AssignTime; - uint16 m_AoE; + timer::duration m_UseDelay; + uint8 m_MaxCharges; + uint16 m_Animation; + timer::duration m_AnimationTime; + timer::duration m_ActivationTime; + uint16 m_ValidTarget; + timer::duration m_ReuseDelay; + timer::time_point m_AssignTime; + timer::time_point m_LastUseTime; + uint16 m_AoE; }; #endif diff --git a/src/map/latent_effect_container.cpp b/src/map/latent_effect_container.cpp index 74f912a7848..97d0057fee5 100644 --- a/src/map/latent_effect_container.cpp +++ b/src/map/latent_effect_container.cpp @@ -732,6 +732,8 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect, bo return false; } + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + // find the latent type from the enum and find the expression to tests againts switch (latentEffect.GetConditionsID()) { @@ -934,7 +936,7 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect, bo break; case LATENT::TIME_OF_DAY: { - uint32 VanadielHour = CVanaTime::getInstance()->getHour(); + uint32 VanadielHour = vanadiel_time::get_hour(vanaTime); switch (latentEffect.GetConditionsValue()) { case 0: @@ -954,7 +956,7 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect, bo } case LATENT::HOUR_OF_DAY: { - uint32 VanadielHour = CVanaTime::getInstance()->getHour(); + uint32 VanadielHour = vanadiel_time::get_hour(vanaTime); switch (latentEffect.GetConditionsValue()) { case 1: @@ -985,33 +987,33 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect, bo break; } case LATENT::FIRESDAY: - expression = CVanaTime::getInstance()->getWeekday() == FIRESDAY; + expression = vanadiel_time::get_weekday(vanaTime) == FIRESDAY; break; case LATENT::EARTHSDAY: - expression = CVanaTime::getInstance()->getWeekday() == EARTHSDAY; + expression = vanadiel_time::get_weekday(vanaTime) == EARTHSDAY; break; case LATENT::WATERSDAY: - expression = CVanaTime::getInstance()->getWeekday() == WATERSDAY; + expression = vanadiel_time::get_weekday(vanaTime) == WATERSDAY; break; case LATENT::WINDSDAY: - expression = CVanaTime::getInstance()->getWeekday() == WINDSDAY; + expression = vanadiel_time::get_weekday(vanaTime) == WINDSDAY; break; case LATENT::DARKSDAY: - expression = CVanaTime::getInstance()->getWeekday() == DARKSDAY; + expression = vanadiel_time::get_weekday(vanaTime) == DARKSDAY; break; case LATENT::ICEDAY: - expression = CVanaTime::getInstance()->getWeekday() == ICEDAY; + expression = vanadiel_time::get_weekday(vanaTime) == ICEDAY; break; case LATENT::LIGHTNINGSDAY: - expression = CVanaTime::getInstance()->getWeekday() == LIGHTNINGDAY; + expression = vanadiel_time::get_weekday(vanaTime) == LIGHTNINGDAY; break; case LATENT::LIGHTSDAY: - expression = CVanaTime::getInstance()->getWeekday() == LIGHTSDAY; + expression = vanadiel_time::get_weekday(vanaTime) == LIGHTSDAY; break; case LATENT::MOON_PHASE: { - uint32 MoonPhase = CVanaTime::getInstance()->getMoonPhase(); - uint32 MoonDirection = CVanaTime::getInstance()->getMoonDirection(); // directions: 1 = waning, 2 = waxing, 0 = neither + uint32 MoonPhase = vanadiel_time::moon::get_phase(vanaTime); + uint32 MoonDirection = vanadiel_time::moon::get_direction(vanaTime); // directions: 1 = waning, 2 = waxing, 0 = neither switch (latentEffect.GetConditionsValue()) { case 0: @@ -1064,11 +1066,11 @@ bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect, bo case LATENT::JOB_MULTIPLE_AT_NIGHT: if (latentEffect.GetConditionsValue() == 0) { - expression = m_POwner->GetMLevel() % 2 == 1 && CVanaTime::getInstance()->SyncTime() == TIME_NIGHT; + expression = m_POwner->GetMLevel() % 2 == 1 && vanadiel_time::get_totd(vanaTime) == vanadiel_time::TOTD::NIGHT; } else { - expression = m_POwner->GetMLevel() % latentEffect.GetConditionsValue() == 0 && CVanaTime::getInstance()->SyncTime() == TIME_NIGHT; + expression = m_POwner->GetMLevel() % latentEffect.GetConditionsValue() == 0 && vanadiel_time::get_totd(vanaTime) == vanadiel_time::TOTD::NIGHT; } break; case LATENT::WEAPON_DRAWN_HP_UNDER: diff --git a/src/map/linkshell.cpp b/src/map/linkshell.cpp index 6216369868b..272c4b346f6 100644 --- a/src/map/linkshell.cpp +++ b/src/map/linkshell.cpp @@ -84,7 +84,7 @@ void CLinkshell::setName(const std::string& name) void CLinkshell::setMessage(const std::string& message, const std::string& poster) { - const auto postTime = static_cast(time(nullptr)); + const auto postTime = earth_time::timestamp(); if (!db::preparedStmt("UPDATE linkshells SET poster = ?, message = ?, messagetime = ? WHERE linkshellid = ?", poster, message, postTime, m_id)) { diff --git a/src/map/lua/lua_ability.cpp b/src/map/lua/lua_ability.cpp index 054ede0e35a..0ac2d7c7cc0 100644 --- a/src/map/lua/lua_ability.cpp +++ b/src/map/lua/lua_ability.cpp @@ -43,7 +43,7 @@ int16 CLuaAbility::getMsg() uint16 CLuaAbility::getRecast() { - return m_PLuaAbility->getRecastTime(); + return static_cast(timer::count_seconds(m_PLuaAbility->getRecastTime())); } uint16 CLuaAbility::getRecastID() @@ -83,7 +83,7 @@ void CLuaAbility::setAnimation(uint16 animationID) void CLuaAbility::setRecast(uint16 recastTime) { - m_PLuaAbility->setRecastTime(recastTime); + m_PLuaAbility->setRecastTime(std::chrono::seconds(recastTime)); } int32 CLuaAbility::getCE() diff --git a/src/map/lua/lua_action.cpp b/src/map/lua/lua_action.cpp index 634fc043b93..317b3333bdc 100644 --- a/src/map/lua/lua_action.cpp +++ b/src/map/lua/lua_action.cpp @@ -56,12 +56,12 @@ uint32 CLuaAction::getPrimaryTargetID() void CLuaAction::setRecast(uint16 recast) { - m_PLuaAction->recast = recast; + m_PLuaAction->recast = std::chrono::seconds(recast); } uint16 CLuaAction::getRecast() { - return m_PLuaAction->recast; + return static_cast(timer::count_seconds(m_PLuaAction->recast)); } void CLuaAction::actionID(uint16 actionid) diff --git a/src/map/lua/lua_baseentity.cpp b/src/map/lua/lua_baseentity.cpp index d224cfdd31c..fea3d3c1b35 100644 --- a/src/map/lua/lua_baseentity.cpp +++ b/src/map/lua/lua_baseentity.cpp @@ -44,6 +44,7 @@ #include "instance.h" #include "ipc_client.h" #include "item_container.h" +#include "items.h" #include "latent_effect_container.h" #include "linkshell.h" #include "map_server.h" @@ -640,7 +641,7 @@ void CLuaBaseEntity::setCharVar(std::string const& varName, int32 value, sol::ob { uint32 varTimestamp = expiry.is() ? expiry.as() : 0; - if (varTimestamp > 0 && varTimestamp <= CVanaTime::getInstance()->getSysTime()) + if (varTimestamp > 0 && varTimestamp <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", varName, varTimestamp)); return; @@ -661,7 +662,7 @@ void CLuaBaseEntity::setCharVarExpiration(std::string const& varName, uint32 exp { if (auto* PChar = dynamic_cast(m_PBaseEntity)) { - if (expiry > 0 && expiry <= CVanaTime::getInstance()->getSysTime()) + if (expiry > 0 && expiry <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", varName, expiry)); return; @@ -701,7 +702,7 @@ void CLuaBaseEntity::setVolatileCharVar(std::string const& varName, int32 value, { uint32 varTimestamp = expiry.is() ? expiry.as() : 0; - if (varTimestamp > 0 && varTimestamp <= CVanaTime::getInstance()->getSysTime()) + if (varTimestamp > 0 && varTimestamp <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", varName, varTimestamp)); return; @@ -823,7 +824,7 @@ uint32 CLuaBaseEntity::getLastOnline() if (auto* PChar = dynamic_cast(m_PBaseEntity)) { - return PChar->lastOnline; + return earth_time::timestamp(PChar->lastOnline); } return 0; @@ -1939,7 +1940,7 @@ bool CLuaBaseEntity::pathThrough(sol::table const& pointsTable, sol::object cons } auto wait = pointData["wait"]; - point.wait = wait.valid() ? wait.get() : 0; + point.wait = wait.valid() ? std::chrono::seconds(wait.get()) : 0s; points.emplace_back(point); } } @@ -1948,7 +1949,7 @@ bool CLuaBaseEntity::pathThrough(sol::table const& pointsTable, sol::object cons // Grab points from array and store in points array for (std::size_t i = 1; i < pointsTable.size(); i += 3) { - points.emplace_back(pathpoint_t{ { (float)pointsTable[i], (float)pointsTable[i + 1], (float)pointsTable[i + 2], 0, 0 }, 0, false }); + points.emplace_back(pathpoint_t{ { (float)pointsTable[i], (float)pointsTable[i + 1], (float)pointsTable[i + 2], 0, 0 }, 0s, false }); } } @@ -2239,7 +2240,7 @@ void CLuaBaseEntity::setElevator(uint8 id, uint32 lowerDoor, uint32 upperDoor, u elevator.Elevator = static_cast(zoneutils::GetEntity(elevatorId, TYPE_NPC)); elevator.animationsReversed = reversed; elevator.state = STATE_ELEVATOR_BOTTOM; - elevator.lastTrigger = 0; + elevator.lastTrigger = vanadiel_time::time_point::min(); if (!elevator.Elevator || !elevator.LowerDoor || !elevator.UpperDoor) { @@ -2251,8 +2252,8 @@ void CLuaBaseEntity::setElevator(uint8 id, uint32 lowerDoor, uint32 upperDoor, u elevator.activated = elevator.id == 0; elevator.isPermanent = elevator.id == 0; - elevator.movetime = 3; - elevator.interval = 8; + elevator.movetime = xi::vanadiel_clock::minutes(3); + elevator.interval = xi::vanadiel_clock::minutes(8); elevator.zoneID = m_PBaseEntity->loc.zone->GetID(); @@ -2282,8 +2283,8 @@ void CLuaBaseEntity::addPeriodicTrigger(uint8 id, uint16 period, uint16 minOffse Trigger_t trigger{}; trigger.id = id; - trigger.period = period; - trigger.minuteOffset = minOffset; + trigger.period = xi::vanadiel_clock::minutes(period); + trigger.minuteOffset = xi::vanadiel_clock::minutes(minOffset); trigger.npc = dynamic_cast(zoneutils::GetEntity(m_PBaseEntity->id, TYPE_NPC)); trigger.lastTrigger = 0; @@ -2499,12 +2500,13 @@ bool CLuaBaseEntity::sendGuild(uint16 guildID, uint8 open, uint8 close, uint8 ho return GUILD_OPEN; } - uint8 VanadielHour = (uint8)CVanaTime::getInstance()->getHour(); + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + uint8 VanadielHour = static_cast(vanadiel_time::get_hour(vanaTime)); GUILDSTATUS status = GUILD_OPEN; // Guild holiday - Removed in 2014 - // uint8 vanadielDay = (uint8)CVanaTime::getInstance()->getWeekday(); + // uint8 vanadielDay = static_cast(vanadiel_time::get_weekday(vanaTime)); // // if (vanadielDay == holiday) // { @@ -2938,7 +2940,7 @@ void CLuaBaseEntity::updateToEntireZone(uint8 statusID, uint8 animation, sol::ob // If this flag is high, update the NPC's name to match the current time if (updateForTime == true) { - PNpc->SetLocalVar("TransportTimestamp", CVanaTime::getInstance()->getVanaTime()); + PNpc->SetLocalVar("TransportTimestamp", earth_time::vanadiel_timestamp()); } PNpc->loc.zone->UpdateEntityPacket(PNpc, ENTITY_UPDATE, UPDATE_COMBAT, true); @@ -4293,7 +4295,7 @@ bool CLuaBaseEntity::addUsedItem(uint16 itemID) { auto* PUsable = static_cast(PItem); PUsable->setQuantity(1); - PUsable->setLastUseTime(CVanaTime::getInstance()->getVanaTime()); + PUsable->setLastUseTime(timer::now()); SlotID = charutils::AddItem(PChar, LOC_INVENTORY, PUsable, false); } else @@ -4695,7 +4697,7 @@ bool CLuaBaseEntity::addLinkpearl(std::string const& lsname, bool equip) return false; } -auto CLuaBaseEntity::addSoulPlate(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp) -> CItem* +auto CLuaBaseEntity::addSoulPlate(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp) -> CItem* { if (m_PBaseEntity->objtype != TYPE_PC) { @@ -4711,7 +4713,7 @@ auto CLuaBaseEntity::addSoulPlate(std::string const& name, uint16 mobFamily, uin PChar->pushPacket(); // Used Soul Plate - CItem* PItem = itemutils::GetItem(2477); + CItem* PItem = itemutils::GetItem(ITEMID::SOUL_PLATE); if (PItem == nullptr) { @@ -4720,7 +4722,7 @@ auto CLuaBaseEntity::addSoulPlate(std::string const& name, uint16 mobFamily, uin } PItem->setQuantity(1); - PItem->setSoulPlateData(name, mobFamily, zeni, skillIndex, fp); + PItem->setSoulPlateData(name, interestData, zeni, skillIndex, fp); auto SlotID = charutils::AddItem(PChar, LOC_INVENTORY, PItem, true); if (SlotID == ERROR_SLOTID) { @@ -6318,7 +6320,7 @@ uint32 CLuaBaseEntity::getPlaytime(sol::object const& shouldUpdate) bool update = (shouldUpdate != sol::lua_nil) ? shouldUpdate.as() : true; auto* PChar = static_cast(m_PBaseEntity); - return PChar->GetPlayTime(update); + return static_cast(timer::count_seconds(PChar->GetPlayTime(update))); } /************************************************************************ @@ -6327,7 +6329,7 @@ uint32 CLuaBaseEntity::getPlaytime(sol::object const& shouldUpdate) * Example : player:getTimeCreated() ************************************************************************/ -int32 CLuaBaseEntity::getTimeCreated() +uint32 CLuaBaseEntity::getTimeCreated() { if (m_PBaseEntity->objtype != TYPE_PC) { @@ -6337,7 +6339,7 @@ int32 CLuaBaseEntity::getTimeCreated() auto* PChar = static_cast(m_PBaseEntity); - return PChar->GetTimeCreated(); + return earth_time::timestamp(PChar->GetTimeCreated()); } /************************************************************************ @@ -11116,7 +11118,7 @@ void CLuaBaseEntity::addPartyEffect(sol::variadic_args va) } CStatusEffect* PEffect = - new CStatusEffect(static_cast(args[0]), args[1], args[2], args[3], args[4], args[5], args[6]); + new CStatusEffect(static_cast(args[0]), args[1], args[2], std::chrono::seconds(args[3]), std::chrono::seconds(args[4]), args[5], args[6]); CBattleEntity* PEntity = ((CBattleEntity*)m_PBaseEntity); @@ -11309,7 +11311,7 @@ uint32 CLuaBaseEntity::getPartyLastMemberJoinedTime() if (PChar->PParty != nullptr) { - return PChar->PParty->GetTimeLastMemberJoined(); + return earth_time::timestamp(timer::to_utc(PChar->PParty->GetTimeLastMemberJoined())); } return 0; @@ -12282,7 +12284,7 @@ void CLuaBaseEntity::addRecast(uint8 recastCont, uint16 recastID, uint32 duratio { RECASTTYPE recastContainer = static_cast(recastCont); - PBattleEntity->PRecastContainer->Add(recastContainer, recastID, duration); + PBattleEntity->PRecastContainer->Add(recastContainer, recastID, std::chrono::seconds(duration)); if (PBattleEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_PBaseEntity; @@ -12307,7 +12309,7 @@ bool CLuaBaseEntity::hasRecast(uint8 rType, uint16 recastID, sol::object const& if (PBattleEntity) { RECASTTYPE recastContainer = static_cast(rType); - uint32 recast = (arg2 != sol::lua_nil) ? arg2.as() : 0; + auto recast = (arg2 != sol::lua_nil) ? std::chrono::seconds(arg2.as()) : 0s; hasRecast = PBattleEntity->PRecastContainer->HasRecast(recastContainer, recastID, recast); } @@ -12334,7 +12336,7 @@ void CLuaBaseEntity::resetRecast(uint8 rType, uint16 recastID) if (PChar->PRecastContainer->Has(recastContainer, recastID)) { PChar->PRecastContainer->Del(recastContainer, recastID); - PChar->PRecastContainer->Add(recastContainer, recastID, 0); + PChar->PRecastContainer->Add(recastContainer, recastID, 0s); } PChar->pushPacket(PChar); @@ -13122,21 +13124,16 @@ void CLuaBaseEntity::updateClaim(sol::object const& entity) * Notes : ************************************************************************/ -bool CLuaBaseEntity::hasClaim(CBattleEntity* PTarget) +bool CLuaBaseEntity::hasClaim(CLuaBaseEntity* PTarget) { - if (m_PBaseEntity->objtype == TYPE_NPC) + auto* PBattleEntity = dynamic_cast(m_PBaseEntity); + if (!PBattleEntity) { ShowWarning("Attempting to check claim for invalid entity type (%s).", m_PBaseEntity->getName()); return false; } - if (PTarget->objtype == TYPE_NPC) - { - ShowWarning("Attempting to check claim for invalid target type (%s).", PTarget->getName()); - return false; - } - - return battleutils::HasClaim(dynamic_cast(m_PBaseEntity), PTarget); + return battleutils::HasClaim(dynamic_cast(m_PBaseEntity), PBattleEntity); } /************************************************************************ @@ -13244,8 +13241,8 @@ bool CLuaBaseEntity::addStatusEffect(sol::variadic_args va) CStatusEffect* PEffect = new CStatusEffect(effectID, effectIcon, power, - tick, - duration, + std::chrono::seconds(tick), + std::chrono::seconds(duration), subType, subPower, tier); @@ -13260,7 +13257,7 @@ bool CLuaBaseEntity::addStatusEffect(sol::variadic_args va) int16 durationModifier = PBattleEntity->getMod(Mod::FOOD_DURATION); if (durationModifier) { - PEffect->SetDuration((uint32)(PEffect->GetDuration() + PEffect->GetDuration() * (durationModifier / 100.0f))); + PEffect->SetDuration(PEffect->GetDuration() + std::chrono::floor(PEffect->GetDuration() * (durationModifier / 100.0f))); } } @@ -13311,8 +13308,8 @@ bool CLuaBaseEntity::addStatusEffectEx(sol::variadic_args va) new CStatusEffect(effectID, effectIcon, power, - tick, - duration, + std::chrono::seconds(tick), + std::chrono::seconds(duration), subType, subPower, tier, @@ -13470,7 +13467,7 @@ bool CLuaBaseEntity::canGainStatusEffect(uint16 effect, sol::object const& power return false; } - CStatusEffect statusEffect(static_cast(effect), 0, power, 0, 0); + CStatusEffect statusEffect(static_cast(effect), 0, power, 0s, 0s); return PBattleEntity->StatusEffectContainer->CanGainStatusEffect(&statusEffect); } @@ -14107,8 +14104,8 @@ bool CLuaBaseEntity::addCorsairRoll(uint8 casterJob, uint8 bustDuration, uint16 CStatusEffect* PEffect = new CStatusEffect(static_cast(effectID), // Effect ID effectID, // Effect Icon (Associated with ID) power, // Power - tick, // Tick - duration, // Duration + std::chrono::seconds(tick), // Tick + std::chrono::seconds(duration), // Duration (arg6 != sol::lua_nil) ? arg6.as() : 0, // SubType or 0 (arg7 != sol::lua_nil) ? arg7.as() : 0, // SubPower or 0 (arg8 != sol::lua_nil) ? arg8.as() : 0 // Tier or 0 @@ -14215,14 +14212,14 @@ bool CLuaBaseEntity::addBardSong(CLuaBaseEntity* PEntity, uint16 effectID, uint1 return false; } - CStatusEffect* PEffect = new CStatusEffect(static_cast(effectID), // Effect ID - effectID, // Effect Icon (Associated with ID) - power, // Power - tick, // Tick - duration, // Duration - subType, // SubType - subPower, // SubPower - tier // Tier + CStatusEffect* PEffect = new CStatusEffect(static_cast(effectID), // Effect ID + effectID, // Effect Icon (Associated with ID) + power, // Power + std::chrono::seconds(tick), // Tick + std::chrono::seconds(duration), // Duration + subType, // SubType + subPower, // SubPower + tier // Tier ); uint8 maxSongs = 2; @@ -16898,7 +16895,7 @@ void CLuaBaseEntity::spawn(sol::object const& despawnSec, sol::object const& res if (respawnSec != sol::lua_nil) { - PMob->m_RespawnTime = respawnSec.as() * 1000; + PMob->m_RespawnTime = std::chrono::seconds(respawnSec.as()); PMob->m_AllowRespawn = true; } else @@ -17008,7 +17005,7 @@ uint32 CLuaBaseEntity::getRespawnTime() if (PMob->m_AllowRespawn) { - return PMob->m_RespawnTime; + return static_cast(timer::count_seconds(PMob->m_RespawnTime)); } return 0; @@ -17037,7 +17034,7 @@ void CLuaBaseEntity::setRespawnTime(uint32 seconds) auto* PMob = static_cast(m_PBaseEntity); - PMob->m_RespawnTime = seconds * 1000; + PMob->m_RespawnTime = std::chrono::seconds(seconds); if (PMob->PAI->IsCurrentState()) { PMob->PAI->GetCurrentState()->ResetEntryTime(); @@ -17510,7 +17507,8 @@ uint32 CLuaBaseEntity::getBattleTime() return 0; } - return static_cast(std::chrono::duration_cast(((CBattleEntity*)m_PBaseEntity)->GetBattleTime()).count()); + auto seconds = timer::count_seconds(static_cast(m_PBaseEntity)->GetBattleTime()); + return static_cast(seconds); } /************************************************************************ @@ -18455,7 +18453,7 @@ uint32 CLuaBaseEntity::getAvailableTraverserStones() * Purpose : Returns the number of Traverser Stones claimed by the player ************************************************************************/ -time_t CLuaBaseEntity::getTraverserEpoch() +uint32 CLuaBaseEntity::getTraverserEpoch() { if (m_PBaseEntity->objtype != TYPE_PC) { @@ -18463,7 +18461,7 @@ time_t CLuaBaseEntity::getTraverserEpoch() } auto* PChar = static_cast(m_PBaseEntity); - return charutils::getTraverserEpoch(PChar); + return earth_time::timestamp(charutils::getTraverserEpoch(PChar)); } /************************************************************************ diff --git a/src/map/lua/lua_baseentity.h b/src/map/lua/lua_baseentity.h index b799f8ed65c..735f1233081 100644 --- a/src/map/lua/lua_baseentity.h +++ b/src/map/lua/lua_baseentity.h @@ -251,7 +251,7 @@ class CLuaBaseEntity bool breakLinkshell(std::string const& lsname); bool addLinkpearl(std::string const& lsname, bool equip); - auto addSoulPlate(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp) -> CItem*; + auto addSoulPlate(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp) -> CItem*; // Trading uint8 getContainerSize(uint8 locationID); @@ -342,7 +342,7 @@ class CLuaBaseEntity void setAnimationSpeed(uint8 speedVal); uint32 getPlaytime(sol::object const& shouldUpdate); - int32 getTimeCreated(); + uint32 getTimeCreated(); // Player Jobs and Levels uint8 getMainJob(); @@ -656,7 +656,7 @@ class CLuaBaseEntity void updateEnmityFromCure(CLuaBaseEntity* PEntity, int32 amount, sol::object const& fixedCE, sol::object const& fixedVE); void resetEnmity(CLuaBaseEntity* PEntity); void updateClaim(sol::object const& entity); - bool hasClaim(CBattleEntity* PTarget); + bool hasClaim(CLuaBaseEntity* PTarget); bool hasEnmity(); auto getNotorietyList() -> sol::table; void clearEnmityForEntity(CLuaBaseEntity* PEntity); @@ -916,7 +916,7 @@ class CLuaBaseEntity void setTHlevel(int16 newLevel); // Sets the Monster's current Treasure Hunter Tier uint32 getAvailableTraverserStones(); - time_t getTraverserEpoch(); + uint32 getTraverserEpoch(); void setTraverserEpoch(); uint32 getClaimedTraverserStones(); void addClaimedTraverserStones(uint16 numStones); diff --git a/src/map/lua/lua_battlefield.cpp b/src/map/lua/lua_battlefield.cpp index be26924bdcc..6eb31c10c43 100644 --- a/src/map/lua/lua_battlefield.cpp +++ b/src/map/lua/lua_battlefield.cpp @@ -61,32 +61,32 @@ uint8 CLuaBattlefield::getArea() uint32 CLuaBattlefield::getTimeLimit() { - return std::chrono::duration_cast(m_PLuaBattlefield->GetTimeLimit()).count(); + return static_cast(timer::count_seconds(m_PLuaBattlefield->GetTimeLimit())); } uint32 CLuaBattlefield::getTimeInside() { - return std::chrono::duration_cast(m_PLuaBattlefield->GetTimeInside()).count(); + return static_cast(timer::count_seconds(m_PLuaBattlefield->GetTimeInside())); } uint32 CLuaBattlefield::getRemainingTime() { - return std::chrono::duration_cast(m_PLuaBattlefield->GetRemainingTime()).count(); + return static_cast(timer::count_seconds(m_PLuaBattlefield->GetRemainingTime())); } uint32 CLuaBattlefield::getFightTick() { - return std::chrono::duration_cast(m_PLuaBattlefield->GetFightTime() - m_PLuaBattlefield->GetStartTime()).count(); + return static_cast(timer::count_seconds(m_PLuaBattlefield->GetFightTime() - m_PLuaBattlefield->GetStartTime())); } uint32 CLuaBattlefield::getWipeTime() { - return std::chrono::duration_cast(m_PLuaBattlefield->GetWipeTime() - get_server_start_time()).count(); + return static_cast(timer::count_seconds(m_PLuaBattlefield->GetWipeTime() - timer::start_time)); } uint32 CLuaBattlefield::getFightTime() { - return std::chrono::duration_cast(get_server_start_time() - m_PLuaBattlefield->GetFightTime()).count(); + return static_cast(timer::count_seconds(timer::start_time - m_PLuaBattlefield->GetFightTime())); } uint32 CLuaBattlefield::getMaxParticipants() @@ -193,7 +193,7 @@ std::tuple CLuaBattlefield::getRecord() const auto& record = m_PLuaBattlefield->GetRecord(); auto name = record.name; - uint32 time = std::chrono::duration_cast(record.time).count(); + uint32 time = timer::count_seconds(record.time); uint32 size = static_cast(record.partySize); return std::make_tuple(name, time, size); @@ -211,7 +211,7 @@ uint64_t CLuaBattlefield::getLocalVar(std::string const& name) uint32 CLuaBattlefield::getLastTimeUpdate() { - auto count = std::chrono::duration_cast(m_PLuaBattlefield->GetLastTimeUpdate()).count(); + auto count = timer::count_seconds(m_PLuaBattlefield->GetLastTimeUpdate()); return count; } @@ -243,7 +243,7 @@ void CLuaBattlefield::setTimeLimit(uint32 seconds) void CLuaBattlefield::setWipeTime(uint32 seconds) { - m_PLuaBattlefield->SetWipeTime(get_server_start_time() + std::chrono::seconds(seconds)); + m_PLuaBattlefield->SetWipeTime(timer::start_time + std::chrono::seconds(seconds)); } void CLuaBattlefield::setRecord(std::string const& name, uint32 seconds) diff --git a/src/map/lua/lua_instance.cpp b/src/map/lua/lua_instance.cpp index 902e9636819..e11d1f9a762 100644 --- a/src/map/lua/lua_instance.cpp +++ b/src/map/lua/lua_instance.cpp @@ -22,6 +22,7 @@ #include "lua_instance.h" #include "common/logging.h" +#include "common/timer.h" #include "instance.h" #include "lua_baseentity.h" @@ -120,7 +121,7 @@ sol::table CLuaInstance::getPets() uint32 CLuaInstance::getTimeLimit() { - uint32 limit = std::chrono::duration_cast(m_PLuaInstance->GetTimeLimit()).count(); + uint32 limit = std::chrono::floor(m_PLuaInstance->GetTimeLimit()).count(); return limit; } @@ -144,7 +145,7 @@ uint8 CLuaInstance::getLevelCap() uint32 CLuaInstance::getLastTimeUpdate() { - auto time_ms = std::chrono::duration_cast(m_PLuaInstance->GetLastTimeUpdate()).count(); + auto time_ms = timer::count_milliseconds(m_PLuaInstance->GetLastTimeUpdate()); return static_cast(time_ms); } @@ -155,7 +156,7 @@ uint32 CLuaInstance::getProgress() uint32 CLuaInstance::getWipeTime() { - auto time_ms = std::chrono::duration_cast(m_PLuaInstance->GetWipeTime()).count(); + auto time_ms = timer::count_milliseconds(m_PLuaInstance->GetWipeTime()); return static_cast(time_ms); } diff --git a/src/map/lua/lua_item.cpp b/src/map/lua/lua_item.cpp index ce654494604..d45609e191a 100644 --- a/src/map/lua/lua_item.cpp +++ b/src/map/lua/lua_item.cpp @@ -324,9 +324,9 @@ bool CLuaItem::isInstalled() return PFurnishing->isInstalled(); } -void CLuaItem::setSoulPlateData(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp) +void CLuaItem::setSoulPlateData(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp) { - m_PLuaItem->setSoulPlateData(name, mobFamily, zeni, skillIndex, fp); + m_PLuaItem->setSoulPlateData(name, interestData, zeni, skillIndex, fp); } auto CLuaItem::getSoulPlateData() -> sol::table @@ -334,11 +334,11 @@ auto CLuaItem::getSoulPlateData() -> sol::table auto data = m_PLuaItem->getSoulPlateData(); sol::table table = lua.create_table(); - table["name"] = std::get<0>(data); - table["mobFamily"] = std::get<1>(data); - table["zeni"] = std::get<2>(data); - table["skillIndex"] = std::get<3>(data); - table["fp"] = std::get<4>(data); + table["name"] = std::get<0>(data); + table["interestData"] = std::get<1>(data); + table["zeni"] = std::get<2>(data); + table["skillIndex"] = std::get<3>(data); + table["fp"] = std::get<4>(data); return table; } diff --git a/src/map/lua/lua_item.h b/src/map/lua/lua_item.h index 410b98c1721..e5fd66bc14c 100644 --- a/src/map/lua/lua_item.h +++ b/src/map/lua/lua_item.h @@ -90,7 +90,7 @@ class CLuaItem bool isInstalled(); - void setSoulPlateData(std::string const& name, uint16 mobFamily, uint8 zeni, uint16 skillIndex, uint8 fp); + void setSoulPlateData(std::string const& name, uint32 interestData, uint8 zeni, uint16 skillIndex, uint8 fp); auto getSoulPlateData() -> sol::table; auto getExData() -> sol::table; // NOTE: This is 0-indexed, to be in line with the underlying C++ data diff --git a/src/map/lua/lua_spell.cpp b/src/map/lua/lua_spell.cpp index 6a839af749b..8bbbdfe48b7 100644 --- a/src/map/lua/lua_spell.cpp +++ b/src/map/lua/lua_spell.cpp @@ -83,12 +83,12 @@ void CLuaSpell::setMPCost(uint16 mpcost) uint32 CLuaSpell::getCastTime() { - return m_PLuaSpell->getCastTime(); + return static_cast(timer::count_milliseconds(m_PLuaSpell->getCastTime())); } void CLuaSpell::setCastTime(uint32 casttime) { - m_PLuaSpell->setCastTime(casttime); + m_PLuaSpell->setCastTime(std::chrono::milliseconds(casttime)); } uint32 CLuaSpell::getPrimaryTargetID() diff --git a/src/map/lua/lua_statuseffect.cpp b/src/map/lua/lua_statuseffect.cpp index 49c347cd2d8..7bdba89d078 100644 --- a/src/map/lua/lua_statuseffect.cpp +++ b/src/map/lua/lua_statuseffect.cpp @@ -71,14 +71,14 @@ uint16 CLuaStatusEffect::getTier() uint32 CLuaStatusEffect::getDuration() { - return m_PLuaStatusEffect->GetDuration() / 1000; + return static_cast(timer::count_milliseconds(m_PLuaStatusEffect->GetDuration())); } //======================================================// uint32 CLuaStatusEffect::getStartTime() { - return (uint32)std::chrono::duration_cast(m_PLuaStatusEffect->GetStartTime() - get_server_start_time()).count(); + return earth_time::timestamp(timer::to_utc(m_PLuaStatusEffect->GetStartTime())); } /************************************************************************ @@ -91,9 +91,9 @@ uint32 CLuaStatusEffect::getLastTick() { uint32 total = 0; - if (m_PLuaStatusEffect->GetTickTime() != 0) + if (m_PLuaStatusEffect->GetTickTime() != 0s) { - uint32 total_ticks = m_PLuaStatusEffect->GetDuration() / m_PLuaStatusEffect->GetTickTime(); + uint32 total_ticks = static_cast(m_PLuaStatusEffect->GetDuration() / m_PLuaStatusEffect->GetTickTime()); uint32 elapsed_ticks = m_PLuaStatusEffect->GetElapsedTickCount(); total = total_ticks - elapsed_ticks; } @@ -110,10 +110,10 @@ uint32 CLuaStatusEffect::getLastTick() uint32 CLuaStatusEffect::getTimeRemaining() { uint32 remaining = 0; - if (m_PLuaStatusEffect->GetDuration() > 0) + if (m_PLuaStatusEffect->GetDuration() > 0s) { - auto duration = std::chrono::duration_cast(server_clock::now() - m_PLuaStatusEffect->GetStartTime()).count(); - remaining = (uint32)std::max(m_PLuaStatusEffect->GetDuration() - duration, std::chrono::seconds::rep{}); + auto duration = m_PLuaStatusEffect->GetStartTime() - timer::now() + m_PLuaStatusEffect->GetDuration(); + remaining = static_cast(timer::count_milliseconds(duration)); } return remaining; @@ -132,7 +132,7 @@ uint32 CLuaStatusEffect::getTickCount() uint32 CLuaStatusEffect::getTick() { - return m_PLuaStatusEffect->GetTickTime(); + return static_cast(timer::count_milliseconds(m_PLuaStatusEffect->GetTickTime())); } //======================================================// @@ -168,12 +168,12 @@ void CLuaStatusEffect::setTier(uint16 tier) void CLuaStatusEffect::setDuration(uint32 duration) { - m_PLuaStatusEffect->SetDuration(duration); + m_PLuaStatusEffect->SetDuration(std::chrono::milliseconds(duration)); } void CLuaStatusEffect::setTick(uint32 tick) { - m_PLuaStatusEffect->SetTickTime(tick); + m_PLuaStatusEffect->SetTickTime(std::chrono::milliseconds(tick)); } /************************************************************************ @@ -184,12 +184,12 @@ void CLuaStatusEffect::setTick(uint32 tick) void CLuaStatusEffect::resetStartTime() { - m_PLuaStatusEffect->SetStartTime(server_clock::now()); + m_PLuaStatusEffect->SetStartTime(timer::now()); } void CLuaStatusEffect::setStartTime(uint32 time) { - m_PLuaStatusEffect->SetStartTime(get_server_start_time() + std::chrono::milliseconds(time)); + m_PLuaStatusEffect->SetStartTime(timer::from_utc(earth_time::time_point(std::chrono::seconds(time)))); } //======================================================// diff --git a/src/map/lua/lua_treasure_pool.cpp b/src/map/lua/lua_treasure_pool.cpp index 9f2cf657822..68e35e823b0 100644 --- a/src/map/lua/lua_treasure_pool.cpp +++ b/src/map/lua/lua_treasure_pool.cpp @@ -154,7 +154,7 @@ auto CLuaTreasurePool::getItems() const -> sol::table sol::table itemRow = lua.create_table(); itemRow["id"] = item.ID; itemRow["slotId"] = item.SlotID; - itemRow["timestamp"] = item.TimeStamp.time_since_epoch().count(); + itemRow["timestamp"] = earth_time::timestamp(timer::to_utc(item.TimeStamp)); sol::table lotters = lua.create_table(); int lotterIndex = 1; diff --git a/src/map/lua/lua_zone.cpp b/src/map/lua/lua_zone.cpp index 7e0149dad6e..0261dbf539c 100644 --- a/src/map/lua/lua_zone.cpp +++ b/src/map/lua/lua_zone.cpp @@ -180,10 +180,7 @@ WEATHER CLuaZone::getWeather() uint32 CLuaZone::getUptime() { - time_point currentTime = std::chrono::system_clock::now(); // Gets the current time - time_point zoneStartTime = get_server_start_time(); // Gets the start time of the zone group (cluster) - - long long uptime = std::chrono::duration_cast(currentTime - zoneStartTime).count(); + long long uptime = timer::count_seconds(timer::get_uptime()); // returns the zone up time in seconds return static_cast(uptime); } diff --git a/src/map/lua/luautils.cpp b/src/map/lua/luautils.cpp index fb66797dc11..374b4c5bb23 100644 --- a/src/map/lua/luautils.cpp +++ b/src/map/lua/luautils.cpp @@ -26,6 +26,7 @@ #include "common/ipc.h" #include "common/logging.h" #include "common/settings.h" +#include "common/timer.h" #include "common/utils.h" #include "common/vana_time.h" #include "common/version.h" @@ -296,7 +297,6 @@ namespace luautils lua.set_function("VanadielMoonDirection", &luautils::VanadielMoonDirection); lua.set_function("VanadielRSERace", &luautils::VanadielRSERace); lua.set_function("VanadielRSELocation", &luautils::VanadielRSELocation); - lua.set_function("SetVanadielTimeOffset", &luautils::SetVanadielTimeOffset); lua.set_function("IsMoonNew", &luautils::IsMoonNew); lua.set_function("IsMoonFull", &luautils::IsMoonFull); lua.set_function("RunElevator", &luautils::StartElevator); @@ -1438,28 +1438,28 @@ namespace luautils { TracyZoneScoped; - return CVanaTime::getInstance()->getVanaTime(); + return earth_time::vanadiel_timestamp(); } uint8 VanadielTOTD() { TracyZoneScoped; - return static_cast(CVanaTime::getInstance()->GetCurrentTOTD()); + return static_cast(vanadiel_time::get_totd()); } uint32 VanadielYear() { TracyZoneScoped; - return CVanaTime::getInstance()->getYear(); + return vanadiel_time::get_year(); } uint32 VanadielMonth() { TracyZoneScoped; - return CVanaTime::getInstance()->getMonth(); + return vanadiel_time::get_month(); } /************************************************************************ @@ -1471,28 +1471,19 @@ namespace luautils uint32 VanadielUniqueDay() { TracyZoneScoped; - - int32 day = CVanaTime::getInstance()->getDayOfTheMonth(); - int32 month = CVanaTime::getInstance()->getMonth(); - int32 year = CVanaTime::getInstance()->getYear(); - - return (year * 360) + (month * 30 - 30) + day; + return vanadiel_time::count_days(vanadiel_time::now().time_since_epoch()); } uint32 VanadielDayOfTheYear() { TracyZoneScoped; - - int32 day = CVanaTime::getInstance()->getDayOfTheMonth(); - int32 month = CVanaTime::getInstance()->getMonth(); - - return (month * 30 - 30) + day; + return vanadiel_time::get_yearday(); } uint32 VanadielDayOfTheMonth() { TracyZoneScoped; - return CVanaTime::getInstance()->getDayOfTheMonth(); + return vanadiel_time::get_monthday(); } /************************************************************************ @@ -1507,19 +1498,19 @@ namespace luautils uint32 VanadielDayOfTheWeek() { TracyZoneScoped; - return CVanaTime::getInstance()->getWeekday(); + return vanadiel_time::get_weekday(); } uint32 VanadielHour() { TracyZoneScoped; - return CVanaTime::getInstance()->getHour(); + return vanadiel_time::get_hour(); } uint32 VanadielMinute() { TracyZoneScoped; - return CVanaTime::getInstance()->getMinute(); + return vanadiel_time::get_minute(); } /************************************************************************ @@ -1545,7 +1536,7 @@ namespace luautils uint32 GetSystemTime() { TracyZoneScoped; - return CVanaTime::getInstance()->getSysTime(); + return earth_time::timestamp(); } /************************************************************************ @@ -1557,7 +1548,8 @@ namespace luautils uint32 JstMidnight() { TracyZoneScoped; - return CVanaTime::getInstance()->getJstMidnight(); + auto jstMidnight = earth_time::jst::get_next_midnight(); + return earth_time::timestamp(jstMidnight); } /************************************************************************ @@ -1569,7 +1561,7 @@ namespace luautils uint32 JstWeekday() { TracyZoneScoped; - return CVanaTime::getInstance()->getJstWeekDay(); + return earth_time::jst::get_weekday(); } /************************************************************************ @@ -1581,11 +1573,11 @@ namespace luautils uint32 NextGameTime(uint32 intervalSeconds) { TracyZoneScoped; - uint32 timeElapsed = CVanaTime::getInstance()->getVanaTime(); - uint32 numPassed = timeElapsed / intervalSeconds; - uint32 secondsRemaining = intervalSeconds - (timeElapsed - (numPassed * intervalSeconds)); + uint32 vanaTimestamp = earth_time::vanadiel_timestamp(); + uint32 secondsMod = vanaTimestamp % intervalSeconds; + auto nextInterval = std::chrono::seconds(vanaTimestamp - secondsMod + intervalSeconds); - return CVanaTime::getInstance()->getSysTime() + secondsRemaining; + return earth_time::timestamp(earth_time::time_point(nextInterval)); } // NOTE: NextJstDay is also defined, and maps to JstMidnight @@ -1593,13 +1585,7 @@ namespace luautils uint32 NextJstWeek() { TracyZoneScoped; - uint32 jstWeekday = (CVanaTime::getInstance()->getJstWeekDay() + 6) % 7; - uint32 nextJstMidnight = CVanaTime::getInstance()->getJstMidnight(); - - // Start with the "Next" Midnight, and apply N days worth of time to it - // jstWeekday is offset by 1 here, so that Monday (JST) is the reference. - - return nextJstMidnight + (6 - jstWeekday) * 60 * 60 * 24; + return earth_time::timestamp(earth_time::get_next_game_week()); } // NOTE: NextConquestTally exists for clarity, and is bound to the above function @@ -1607,33 +1593,25 @@ namespace luautils uint32 VanadielMoonPhase() { TracyZoneScoped; - return CVanaTime::getInstance()->getMoonPhase(); - } - - bool SetVanadielTimeOffset(int32 offset) - { - TracyZoneScoped; - uint32 custom = CVanaTime::getInstance()->getCustomEpoch(); - CVanaTime::getInstance()->setCustomEpoch((custom ? custom : VTIME_BASEDATE) - offset); - return true; + return vanadiel_time::moon::get_phase(); } uint8 VanadielMoonDirection() { TracyZoneScoped; - return CVanaTime::getInstance()->getMoonDirection(); + return vanadiel_time::moon::get_direction(); } uint8 VanadielRSERace() { TracyZoneScoped; - return CVanaTime::getInstance()->getRSERace(); + return vanadiel_time::rse::get_race(); } uint8 VanadielRSELocation() { TracyZoneScoped; - return CVanaTime::getInstance()->getRSELocation(); + return vanadiel_time::rse::get_location(); } bool IsMoonNew() @@ -1643,9 +1621,10 @@ namespace luautils // Waning (decreasing) from 10% to 0%, // Waxing (increasing) from 0% to 5%. - uint8 phase = CVanaTime::getInstance()->getMoonPhase(); + vanadiel_time::time_point currentVanaTime = vanadiel_time::now(); + auto phase = vanadiel_time::moon::get_phase(currentVanaTime); - switch (CVanaTime::getInstance()->getMoonDirection()) + switch (vanadiel_time::moon::get_direction(currentVanaTime)) { case 0: // None if (phase == 0) @@ -1677,9 +1656,10 @@ namespace luautils // Waxing (increasing) from 90% to 100%, // Waning (decending) from 100% to 95%. - uint8 phase = CVanaTime::getInstance()->getMoonPhase(); + vanadiel_time::time_point currentVanaTime = vanadiel_time::now(); + auto phase = vanadiel_time::moon::get_phase(currentVanaTime); - switch (CVanaTime::getInstance()->getMoonDirection()) + switch (vanadiel_time::moon::get_direction(currentVanaTime)) { case 0: // None if (phase == 100) @@ -1735,7 +1715,7 @@ namespace luautils if (arg3.is()) { - PMob->m_RespawnTime = arg3.as() * 1000; + PMob->m_RespawnTime = std::chrono::seconds(arg3.as()); PMob->m_AllowRespawn = true; } else @@ -1971,7 +1951,7 @@ namespace luautils ShowTraceFmt("luautils::OnGameIn: {}", PChar->getName()); - callGlobal("xi.player.onGameIn", PChar, PChar->GetPlayTime(false) == 0, zoning); + callGlobal("xi.player.onGameIn", PChar, PChar->GetPlayTime(false) == 0s, zoning); } void OnZoneIn(CCharEntity* PChar) @@ -3172,7 +3152,7 @@ namespace luautils } auto name = PBattlefield->GetName(); - auto seconds = std::chrono::duration_cast(PBattlefield->GetTimeInside()).count(); + auto seconds = timer::count_seconds(PBattlefield->GetTimeInside()); if (invokeBattlefieldEvent(PBattlefield->GetID(), "onBattlefieldTick", PBattlefield, seconds) == 0) { @@ -4570,7 +4550,7 @@ namespace luautils { uint32 varTimestamp = expiry.is() ? expiry.as() : 0; - if (varTimestamp > 0 && varTimestamp <= CVanaTime::getInstance()->getSysTime()) + if (varTimestamp > 0 && varTimestamp <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", name, varTimestamp)); return; @@ -4588,7 +4568,7 @@ namespace luautils { uint32 varTimestamp = expiry.is() ? expiry.as() : 0; - if (varTimestamp > 0 && varTimestamp <= CVanaTime::getInstance()->getSysTime()) + if (varTimestamp > 0 && varTimestamp <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", varName, varTimestamp)); return; @@ -4607,7 +4587,7 @@ namespace luautils { uint32 varTimestamp = expiry.is() ? expiry.as() : 0; - if (varTimestamp > 0 && varTimestamp <= CVanaTime::getInstance()->getSysTime()) + if (varTimestamp > 0 && varTimestamp <= earth_time::timestamp()) { ShowWarning(fmt::format("Attempting to set variable '{}' with an expired time: {}", varName, varTimestamp)); return; @@ -4847,7 +4827,7 @@ namespace luautils if (PMob != nullptr) { - return PMob->m_RespawnTime / 1000; + return static_cast(timer::count_seconds(PMob->m_RespawnTime)); } ShowError("luautils::GetMobAction: mob <%u> was not found", mobid); @@ -5539,7 +5519,7 @@ namespace luautils const auto respawn = table["respawn"].get_or(0); if (respawn > 0) { - PMob->m_RespawnTime = respawn * 1000; + PMob->m_RespawnTime = std::chrono::seconds(respawn); PMob->m_AllowRespawn = true; } else diff --git a/src/map/lua/luautils.h b/src/map/lua/luautils.h index 3f81cc4f16a..a4572deb97d 100644 --- a/src/map/lua/luautils.h +++ b/src/map/lua/luautils.h @@ -262,7 +262,6 @@ namespace luautils uint8 VanadielMoonDirection(); uint8 VanadielRSERace(); uint8 VanadielRSELocation(); - bool SetVanadielTimeOffset(int32 offset); bool IsMoonNew(); bool IsMoonFull(); void StartElevator(uint32 ElevatorID); diff --git a/src/map/map_constants.h b/src/map/map_constants.h index 5c48b04a10e..de321e74c1a 100644 --- a/src/map/map_constants.h +++ b/src/map/map_constants.h @@ -22,6 +22,7 @@ #pragma once #include "common/cbasetypes.h" +#include "common/timer.h" #include #include @@ -50,10 +51,10 @@ static constexpr auto kLogicUpdateInterval = std::chrono::milliseconds(static_ca static constexpr auto kTriggerAreaInterval = std::chrono::milliseconds(static_cast(1000.0f / (kLogicUpdateRate * 2.0f))); // Split betweek task manager and networking workload (200ms) -static constexpr auto kMainLoopInterval = std::chrono::milliseconds(200); +static constexpr auto kMainLoopInterval = 200ms; // If the main loop is more than 100ms behind, we're in trouble. -static constexpr auto kMainLoopBacklogThreshold = std::chrono::milliseconds(100); +static constexpr auto kMainLoopBacklogThreshold = 100ms; // Packet & networking constants static constexpr auto kMaxBufferSize = 2500U; diff --git a/src/map/map_networking.cpp b/src/map/map_networking.cpp index e7adf7ac1d9..bebee11f471 100644 --- a/src/map/map_networking.cpp +++ b/src/map/map_networking.cpp @@ -146,22 +146,21 @@ void MapNetworking::tapStatistics() TotalPacketsDelayedPerTick = 0U; } -auto MapNetworking::doSocketsBlocking(duration next) -> duration +auto MapNetworking::doSocketsBlocking(timer::duration next) -> timer::duration { TracyZoneScoped; - const auto start = server_clock::now(); + const auto start = timer::now(); message::handle_incoming(); - const auto duration = std::chrono::duration_cast(next - std::chrono::duration_cast(next)); - mapSocket_->recvFor(duration); + mapSocket_->recvFor(next); _sql->TryPing(); tapStatistics(); - return server_clock::now() - start; + return timer::now() - start; } void MapNetworking::handle_incoming_packet(const std::error_code& ec, std::span buffer, IPP ipp) @@ -454,7 +453,7 @@ int32 MapNetworking::parse(uint8* buff, size_t* buffsize, MapSession* map_sessio { // Update the time we last got a char sync packet // The client can spam some other packets when trying to zone, preventing timely session deletions - map_session_data->last_update = time(nullptr); + map_session_data->last_update = timer::now(); } for (uint8* SmallPD_ptr = PacketData_Begin; SmallPD_ptr + (ref(SmallPD_ptr, 1) & 0xFE) * 2 <= PacketData_End && (ref(SmallPD_ptr, 1) & 0xFE); @@ -551,7 +550,7 @@ int32 MapNetworking::parse(uint8* buff, size_t* buffsize, MapSession* map_sessio } ref(map_session_data->server_packet_data.data(), 2) = SmallPD_Code; - ref(map_session_data->server_packet_data.data(), 8) = (uint32)time(nullptr); + ref(map_session_data->server_packet_data.data(), 8) = earth_time::timestamp(); PBuff = map_session_data->server_packet_data; *buffsize = map_session_data->server_packet_size; @@ -582,7 +581,7 @@ int32 MapNetworking::send_parse(uint8* buff, size_t* buffsize, MapSession* map_s ref(buff, 2) = map_session_data->client_packet_id; // save the current time (32 BIT!) - ref(buff, 8) = (uint32)time(nullptr); + ref(buff, 8) = earth_time::timestamp(); // build a large package, consisting of several small packets CCharEntity* PChar = map_session_data->PChar; diff --git a/src/map/map_networking.h b/src/map/map_networking.h index 20bbd17870e..4b8d84e6069 100644 --- a/src/map/map_networking.h +++ b/src/map/map_networking.h @@ -45,7 +45,7 @@ class MapNetworking // void tapStatistics(); - auto doSocketsBlocking(duration) -> duration; + auto doSocketsBlocking(timer::duration) -> timer::duration; // TODO: Pass around std::span instead of uint8* and size_t* // TODO: Stop changing the buffsize size_t as we go along diff --git a/src/map/map_server.cpp b/src/map/map_server.cpp index d65e2d70f11..600d1c05840 100644 --- a/src/map/map_server.cpp +++ b/src/map/map_server.cpp @@ -205,7 +205,7 @@ void MapServer::prepareWatchdog() ShowCritical(outputStr); // Allow some time for logging to flush - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(200ms); throw std::runtime_error("Watchdog thread time exceeded. Killing process."); } @@ -219,32 +219,34 @@ void MapServer::run() while (Application::isRunning()) { - duration tasksDuration; - duration networkDuration; - duration tickDuration; + timer::duration tasksDuration; + timer::duration networkDuration; + timer::duration tickDuration; - const auto tickStart = server_clock::now(); + const auto tickStart = timer::now(); { - tasksDuration = CTaskManager::getInstance()->doExpiredTasks(tickStart); - networkDuration = networking_->doSocketsBlocking(kMainLoopInterval - tasksDuration); // Use tick remainder for networking - watchdog_->update(); + tasksDuration = CTaskManager::getInstance()->doExpiredTasks(tickStart); + // Use tick remainder for networking with a maximum to ensure that the network phase + // doesn't starve and a minimum to prevent bumping up against the time limit. + networkDuration = networking_->doSocketsBlocking(kMainLoopInterval - std::clamp(tasksDuration, 50ms, 150ms)); } - tickDuration = server_clock::now() - tickStart; - tasksDuration = tickDuration - networkDuration; // Since we don't measure logic directly, we can calculate it based on the total and network durations + tickDuration = timer::now() - tickStart; const auto tickDiffTime = kMainLoopInterval - tickDuration; - mapStatistics_->set(MapStatistics::Key::TasksTickTime, getMilliseconds(tasksDuration)); - mapStatistics_->set(MapStatistics::Key::NetworkTickTime, getMilliseconds(networkDuration)); - mapStatistics_->set(MapStatistics::Key::TotalTickTime, getMilliseconds(tickDuration)); - mapStatistics_->set(MapStatistics::Key::TickDiffTime, getMilliseconds(tickDiffTime)); + mapStatistics_->set(MapStatistics::Key::TasksTickTime, timer::count_milliseconds(tasksDuration)); + mapStatistics_->set(MapStatistics::Key::NetworkTickTime, timer::count_milliseconds(networkDuration)); + mapStatistics_->set(MapStatistics::Key::TotalTickTime, timer::count_milliseconds(tickDuration)); + mapStatistics_->set(MapStatistics::Key::TickDiffTime, timer::count_milliseconds(tickDiffTime)); mapStatistics_->flush(); DebugPerformanceFmt("Tasks: {}ms, Network: {}ms, Total: {}ms, Diff/Sleep: {}ms", - getMilliseconds(tasksDuration), - getMilliseconds(networkDuration), - getMilliseconds(tickDuration), - getMilliseconds(tickDiffTime)); + timer::count_milliseconds(tasksDuration), + timer::count_milliseconds(networkDuration), + timer::count_milliseconds(tickDuration), + timer::count_milliseconds(tickDiffTime)); + + watchdog_->update(); if (tickDiffTime > 0ms) { @@ -252,7 +254,7 @@ void MapServer::run() } else if (tickDiffTime < -kMainLoopBacklogThreshold) { - RATE_LIMIT(15s, ShowWarningFmt("Main loop is running {}ms behind, performance is degraded!", -getMilliseconds(tickDiffTime))); + RATE_LIMIT(15s, ShowWarningFmt("Main loop is running {}ms behind, performance is degraded!", -timer::count_milliseconds(tickDiffTime))); } } } @@ -360,21 +362,19 @@ void MapServer::do_init() monstrosity::LoadStaticData(); - CVanaTime::getInstance()->setCustomEpoch(settings::get("map.VANADIEL_TIME_EPOCH")); - zoneutils::InitializeWeather(); // Need VanaTime initialized CTransportHandler::getInstance()->InitializeTransport(mapIPP); - CTaskManager::getInstance()->AddTask("time_server", server_clock::now(), nullptr, CTaskManager::TASK_INTERVAL, kTimeServerTickInterval, time_server); - CTaskManager::getInstance()->AddTask("map_cleanup", server_clock::now(), nullptr, CTaskManager::TASK_INTERVAL, 5s, std::bind(&MapServer::map_cleanup, this, std::placeholders::_1, std::placeholders::_2)); - CTaskManager::getInstance()->AddTask("garbage_collect", server_clock::now(), nullptr, CTaskManager::TASK_INTERVAL, 15min, std::bind(&MapServer::map_garbage_collect, this, std::placeholders::_1, std::placeholders::_2)); - CTaskManager::getInstance()->AddTask("persist_server_vars", server_clock::now(), nullptr, CTaskManager::TASK_INTERVAL, 1min, serverutils::PersistVolatileServerVars); + CTaskManager::getInstance()->AddTask("time_server", timer::now(), nullptr, CTaskManager::TASK_INTERVAL, kTimeServerTickInterval, time_server); + CTaskManager::getInstance()->AddTask("map_cleanup", timer::now(), nullptr, CTaskManager::TASK_INTERVAL, 5s, std::bind(&MapServer::map_cleanup, this, std::placeholders::_1, std::placeholders::_2)); + CTaskManager::getInstance()->AddTask("garbage_collect", timer::now(), nullptr, CTaskManager::TASK_INTERVAL, 15min, std::bind(&MapServer::map_garbage_collect, this, std::placeholders::_1, std::placeholders::_2)); + CTaskManager::getInstance()->AddTask("persist_server_vars", timer::now(), nullptr, CTaskManager::TASK_INTERVAL, 1min, serverutils::PersistVolatileServerVars); - zoneutils::TOTDChange(CVanaTime::getInstance()->GetCurrentTOTD()); // This tells the zones to spawn stuff based on time of day conditions (such as undead at night) + zoneutils::TOTDChange(vanadiel_time::get_totd()); // This tells the zones to spawn stuff based on time of day conditions (such as undead at night) ShowInfo("do_init: Removing expired database variables"); - uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); + uint32 currentTimestamp = earth_time::timestamp(); db::preparedStmt("DELETE FROM char_vars WHERE expiry > 0 AND expiry <= ?", currentTimestamp); db::preparedStmt("DELETE FROM server_variables WHERE expiry > 0 AND expiry <= ?", currentTimestamp); @@ -413,16 +413,13 @@ void MapServer::do_final() zoneutils::FreeZoneList(); CTaskManager::delInstance(); - CVanaTime::delInstance(); Async::delInstance(); - timer_final(); - luautils::cleanup(); logging::ShutDown(); } -int32 MapServer::map_cleanup(time_point tick, CTaskManager::CTask* PTask) +int32 MapServer::map_cleanup(timer::time_point tick, CTaskManager::CTask* PTask) { TracyZoneScoped; @@ -438,7 +435,7 @@ int32 MapServer::map_cleanup(time_point tick, CTaskManager::CTask* PTask) return 0; } -int32 MapServer::map_garbage_collect(time_point tick, CTaskManager::CTask* PTask) +int32 MapServer::map_garbage_collect(timer::time_point tick, CTaskManager::CTask* PTask) { TracyZoneScoped; diff --git a/src/map/map_server.h b/src/map/map_server.h index 7ab5a2873b5..3d8af9edbc9 100644 --- a/src/map/map_server.h +++ b/src/map/map_server.h @@ -24,6 +24,7 @@ #include "pch.h" #include "common/application.h" +#include "common/timer.h" #include "common/watchdog.h" #include "zone.h" @@ -72,8 +73,8 @@ class MapServer final : public Application // Maintenance // - int32 map_cleanup(time_point tick, CTaskManager::CTask* PTask); // Clean up timed out players - int32 map_garbage_collect(time_point tick, CTaskManager::CTask* PTask); + int32 map_cleanup(timer::time_point tick, CTaskManager::CTask* PTask); // Clean up timed out players + int32 map_garbage_collect(timer::time_point tick, CTaskManager::CTask* PTask); // // Accessors diff --git a/src/map/map_session.h b/src/map/map_session.h index 6a8bf0aebd8..eed1713f869 100644 --- a/src/map/map_session.h +++ b/src/map/map_session.h @@ -24,6 +24,7 @@ #include "common/blowfish.h" #include "common/cbasetypes.h" #include "common/ipp.h" +#include "common/timer.h" #include "map_constants.h" @@ -33,16 +34,16 @@ class CCharEntity; struct MapSession { - IPP client_ipp = {}; - uint16 client_packet_id = 0; // id of the last packet that came from the client - uint16 server_packet_id = 0; // id of the last packet sent by the server - NetworkBuffer server_packet_data = {}; // data of the packet, which was previously sent to the client - size_t server_packet_size = 0; // the size of the packet that was previously sent to the client - time_t last_update = 0; // time of last packet recv - blowfish_t blowfish = {}; // unique decypher keys, these are the currently expected keys - CCharEntity* PChar = nullptr; // game char - uint8 shuttingDown = 0; // prevents double session closing - uint32 charID = 0; + IPP client_ipp = {}; + uint16 client_packet_id = 0; // id of the last packet that came from the client + uint16 server_packet_id = 0; // id of the last packet sent by the server + NetworkBuffer server_packet_data = {}; // data of the packet, which was previously sent to the client + size_t server_packet_size = 0; // the size of the packet that was previously sent to the client + timer::time_point last_update = {}; // time of last packet recv + blowfish_t blowfish = {}; // unique decypher keys, these are the currently expected keys + CCharEntity* PChar = nullptr; // game char + uint8 shuttingDown = 0; // prevents double session closing + uint32 charID = 0; // Store old blowfish data, when a player recieves 0x00B their key should increment // If it doesn't, and we can still successfully decrypt here, that means we need to resend 0x00B. diff --git a/src/map/map_session_container.cpp b/src/map/map_session_container.cpp index f255df1a6d4..8410f75e698 100644 --- a/src/map/map_session_container.cpp +++ b/src/map/map_session_container.cpp @@ -55,7 +55,7 @@ auto MapSessionContainer::createSession(IPP ipp) -> MapSession* auto map_session_data = std::make_unique(); - map_session_data->last_update = time(nullptr); + map_session_data->last_update = timer::now(); map_session_data->client_ipp = ipp; sessions_[ipp] = std::move(map_session_data); @@ -149,8 +149,9 @@ void MapSessionContainer::cleanupSessions(IPP mapIPP) auto& map_session_data = it->second; CCharEntity* PChar = map_session_data->PChar; + auto now = timer::now(); - if ((time(nullptr) - map_session_data->last_update) > 5) + if (now > map_session_data->last_update + 5s) { if (PChar != nullptr && !PChar->isLinkDead) { @@ -166,7 +167,8 @@ void MapSessionContainer::cleanupSessions(IPP mapIPP) } } - if ((time(nullptr) - map_session_data->last_update) > settings::get("map.MAX_TIME_LASTUPDATE")) + auto timeoutSetting = settings::get("map.MAX_TIME_LASTUPDATE"); + if (now > map_session_data->last_update + std::chrono::seconds(timeoutSetting)) { bool otherMap = false; diff --git a/src/map/map_socket.cpp b/src/map/map_socket.cpp index 15559bd3c90..37289af6fd0 100644 --- a/src/map/map_socket.cpp +++ b/src/map/map_socket.cpp @@ -73,7 +73,7 @@ void MapSocket::startReceive() }); } -void MapSocket::recvFor(duration duration) +void MapSocket::recvFor(timer::duration duration) { TracyZoneScoped; diff --git a/src/map/map_socket.h b/src/map/map_socket.h index 6d58aa8331f..2cde22b8126 100644 --- a/src/map/map_socket.h +++ b/src/map/map_socket.h @@ -40,7 +40,7 @@ class MapSocket MapSocket(uint16 port, ReceiveFn onReceiveFn); // TODO: Move passing in onReceiveFn to recvFor ~MapSocket(); - void recvFor(duration duration); + void recvFor(timer::duration duration); void send(const IPP& ipp, std::span buffer); private: diff --git a/src/map/mobskill.cpp b/src/map/mobskill.cpp index c9717cb9c87..1259a3c9241 100644 --- a/src/map/mobskill.cpp +++ b/src/map/mobskill.cpp @@ -33,8 +33,8 @@ CMobSkill::CMobSkill(uint16 id) , m_Distance(0) , m_Flag(0) , m_ValidTarget(0) -, m_AnimationTime(0) -, m_ActivationTime(0) +, m_AnimationTime(0s) +, m_ActivationTime(0s) , m_Message(0) , m_TP(0) , m_HPP(0) @@ -164,12 +164,12 @@ void CMobSkill::setHPP(uint8 hpp) m_HPP = hpp; } -void CMobSkill::setAnimationTime(uint16 AnimationTime) +void CMobSkill::setAnimationTime(timer::duration AnimationTime) { m_AnimationTime = AnimationTime; } -void CMobSkill::setActivationTime(uint16 ActivationTime) +void CMobSkill::setActivationTime(timer::duration ActivationTime) { m_ActivationTime = ActivationTime; } @@ -331,12 +331,12 @@ uint16 CMobSkill::getValidTargets() const return m_ValidTarget; } -uint16 CMobSkill::getAnimationTime() const +timer::duration CMobSkill::getAnimationTime() const { return m_AnimationTime; } -uint16 CMobSkill::getActivationTime() const +timer::duration CMobSkill::getActivationTime() const { return m_ActivationTime; } diff --git a/src/map/mobskill.h b/src/map/mobskill.h index 60cf07c06a2..e172c3d5126 100644 --- a/src/map/mobskill.h +++ b/src/map/mobskill.h @@ -65,28 +65,28 @@ class CMobSkill bool isBloodPactWard() const; bool isBloodPactRage() const; - uint16 getID() const; - uint16 getAnimationID() const; - uint8 getAoe() const; - float getDistance() const; - uint8 getFlag() const; - uint16 getAnimationTime() const; - uint16 getActivationTime() const; - uint16 getMsg() const; - uint16 getAoEMsg() const; - uint16 getValidTargets() const; - int16 getTP() const; - uint8 getHPP() const; - auto getTargets() const -> const std::vector&; - uint16 getTotalTargets() const; - uint32 getPrimaryTargetID() const; - uint16 getMsgForAction() const; - float getRadius() const; - int16 getParam() const; - uint8 getKnockback() const; - uint8 getPrimarySkillchain() const; - uint8 getSecondarySkillchain() const; - uint8 getTertiarySkillchain() const; + uint16 getID() const; + uint16 getAnimationID() const; + uint8 getAoe() const; + float getDistance() const; + uint8 getFlag() const; + timer::duration getAnimationTime() const; + timer::duration getActivationTime() const; + uint16 getMsg() const; + uint16 getAoEMsg() const; + uint16 getValidTargets() const; + int16 getTP() const; + uint8 getHPP() const; + auto getTargets() const -> const std::vector&; + uint16 getTotalTargets() const; + uint32 getPrimaryTargetID() const; + uint16 getMsgForAction() const; + float getRadius() const; + int16 getParam() const; + uint8 getKnockback() const; + uint8 getPrimarySkillchain() const; + uint8 getSecondarySkillchain() const; + uint8 getTertiarySkillchain() const; bool isDamageMsg() const; @@ -96,8 +96,8 @@ class CMobSkill void setAoeRadius(float aoeRadius); void setDistance(float distance); void setFlag(uint8 flag); - void setAnimationTime(uint16 AnimationTime); - void setActivationTime(uint16 ActivationTime); + void setAnimationTime(timer::duration AnimationTime); + void setActivationTime(timer::duration ActivationTime); void setMsg(uint16 msg); void setValidTargets(uint16 targ); void setTP(int16 tp); @@ -115,25 +115,25 @@ class CMobSkill void setName(const std::string& name); private: - uint16 m_ID; - uint16 m_TotalTargets; - uint32 m_primaryTargetID; // Primary target ID - int16 m_Param; - uint16 m_AnimID; - uint8 m_Aoe; // Defines the type of AOE - float m_AoeRadius; // Radius of any aoe skill - float m_Distance; // Distance at which the skill will be triggered - uint8 m_Flag; - uint16 m_ValidTarget; - uint16 m_AnimationTime; // how long the tp animation lasts for in ms - uint16 m_ActivationTime; // how long the mob prepares the tp move for - uint16 m_Message; // message param, scripters can edit this depending on self/resist/etc. - int16 m_TP; // the tp at the time of finish readying (for scripts) - uint8 m_HPP; // HPP at the time of using mob skill (for scripts) - uint8 m_knockback; // knockback value (0-7) - uint8 m_primarySkillchain; - uint8 m_secondarySkillchain; - uint8 m_tertiarySkillchain; + uint16 m_ID; + uint16 m_TotalTargets; + uint32 m_primaryTargetID; // Primary target ID + int16 m_Param; + uint16 m_AnimID; + uint8 m_Aoe; // Defines the type of AOE + float m_AoeRadius; // Radius of any aoe skill + float m_Distance; // Distance at which the skill will be triggered + uint8 m_Flag; + uint16 m_ValidTarget; + timer::duration m_AnimationTime; // how long the tp animation lasts for in ms + timer::duration m_ActivationTime; // how long the mob prepares the tp move for + uint16 m_Message; // message param, scripters can edit this depending on self/resist/etc. + int16 m_TP; // the tp at the time of finish readying (for scripts) + uint8 m_HPP; // HPP at the time of using mob skill (for scripts) + uint8 m_knockback; // knockback value (0-7) + uint8 m_primarySkillchain; + uint8 m_secondarySkillchain; + uint8 m_tertiarySkillchain; std::string m_name; diff --git a/src/map/modifier.h b/src/map/modifier.h index 6674f7938ac..e9695c9fc73 100644 --- a/src/map/modifier.h +++ b/src/map/modifier.h @@ -439,11 +439,12 @@ enum class Mod ELEMENTAL_DEBUFF_EFFECT = 1150, // Increase stat reduction by N, and DoT by N/2 HP per tick // Red Mage - BLINK = 299, // Tracks blink shadows - STONESKIN = 300, // Tracks stoneskin HP pool - PHALANX = 301, // Tracks direct damage reduction - ENF_MAG_POTENCY = 290, // Increases Enfeebling magic potency % - ENHANCES_SABOTEUR = 297, // Increases Saboteur Potency % + BLINK = 299, // Tracks blink shadows + STONESKIN = 300, // Tracks stoneskin HP pool + PHALANX = 301, // Tracks direct damage reduction + ENF_MAG_POTENCY = 290, // Increases Enfeebling magic potency % + ENF_MAG_DURATION = 1151, // Increases enfeebling magic duration % + ENHANCES_SABOTEUR = 297, // Increases Saboteur Potency % // Thief FLEE_DURATION = 93, // Flee duration in seconds @@ -501,18 +502,20 @@ enum class Mod ENHANCES_ABSORB_EFFECTS = 1136, // Absorb Spell duration +x seconds (Enhances "Absorb" effects) AUGMENTS_ABSORB = 1137, // Non-Liberator Absorb Spell potency +x% (Augments "Absorb" effects) ABSORB_EFFECT_DURATION = 1138, // Absorb Spell duration +% ("Absorb" effect duration +x%) + AUGMENTS_ABSORB_TP = 1153, // Increases absorb-TP potency, stacks with AUGMENTS_ABSORB // Beastmaster - TAME = 304, // Additional percent chance to charm - CHARM_TIME = 360, // extends the charm time only, no effect of charm chance - REWARD_HP_BONUS = 364, // Percent to add to reward HP healed. (364) - CHARM_CHANCE = 391, // extra chance to charm (light+apollo staff ect) - FERAL_HOWL_DURATION = 503, // +20% duration per merit when wearing augmented Monster Jackcoat +2 - JUG_LEVEL_RANGE = 564, // Decreases the level range of spawned jug pets. Maxes out at 2. - CALL_BEAST_DELAY = 273, // Lowers Call Beast recast - SIC_READY_RECAST = 1052, // SIC/Ready recast reduction (seconds) - TANDEM_STRIKE_POWER = 271, // Grants a bonus to your and your pet's accuracy and magic accuracy when you and your pet are attacking the same target. - TANDEM_BLOW_POWER = 272, // Reduces amount of TP gained by enemies when striking them if you and your pet are attacking the same target. + TAME = 304, // Additional percent chance to charm + CHARM_TIME = 360, // extends the charm time only, no effect of charm chance + REWARD_HP_BONUS = 364, // Percent to add to reward HP healed. (364) + CHARM_CHANCE = 391, // extra chance to charm (light+apollo staff ect) + FERAL_HOWL_DURATION = 503, // +20% duration per merit when wearing augmented Monster Jackcoat +2 + JUG_LEVEL_RANGE = 564, // Decreases the level range of spawned jug pets. Maxes out at 2. + CALL_BEAST_DELAY = 273, // Lowers Call Beast recast + SIC_READY_RECAST = 1052, // SIC/Ready recast reduction (seconds) + TANDEM_STRIKE_POWER = 271, // Grants a bonus to your and your pet's accuracy and magic accuracy when you and your pet are attacking the same target. + TANDEM_BLOW_POWER = 272, // Reduces amount of TP gained by enemies when striking them if you and your pet are attacking the same target. + ENHANCES_MONSTER_CORRELATION = 1155, // Grants your pet acc +X and attp +X% against a weaker opposing ecosystem. Typically applied to pet, not owner (item_mods_pet.sql) // Bard MINNE_EFFECT = 433, // @@ -614,7 +617,7 @@ enum class Mod BP_DELAY_II = 541, // Blood Pact Delay Reduction II BP_DAMAGE = 126, // Blood Pact: Rage Damage increase percentage BLOOD_BOON = 913, // Occasionally cuts down MP cost of Blood Pact abilities. Does not affect abilities that require Astral Flow. - AVATARS_FAVOR_ENHANCE = 141, // Enhances Avatars Favor Effect by 1 tier per point + AVATARS_FAVOR_ENHANCE = 1154, // Enhances Avatars Favor Effect by 1 tier per point AVATAR_LVL_BONUS = 1040, // Avatar: Lv.+ (Increases all avatar's base level above 99) CARBUNCLE_LVL_BONUS = 1041, // Carbuncle: Lv.+ (Increases Carbuncle's base level above 99) CAIT_SITH_LVL_BONUS = 1042, // Cait Sith: Lv.+ (Increases Cait Sith's base level above 99) @@ -1088,16 +1091,14 @@ enum class Mod PARRY_HP_RECOVERY = 1135, // Recover HP on successful parry. // TODO: These mods are not yet implemented. - ENF_MAG_DURATION = 1151, // TODO: Increase enfeebling spell duration (percent) - REWARD_RECAST = 1152, // TODO: Reward recast time reduction (seconds) - AUGMENTS_ABSORB_TP = 1153, // TODO: Increases absorb-TP potency, stacks with AUGMENTS_ABSORB + REWARD_RECAST = 1152, // TODO: Reward recast time reduction (seconds) // IF YOU ADD ANY NEW MODIFIER HERE, ADD IT IN scripts/enum/mod.lua ASWELL! // The spares take care of finding the next ID to use so long as we don't forget to list IDs that have been freed up by refactoring. // 570 through 825 used by WS DMG mods these are not spares. // - // SPARE IDs: 1154 and onward + // SPARE IDs: 1156 and onward }; // temporary workaround for using enum class as unordered_map key until compilers support it diff --git a/src/map/monstrosity.cpp b/src/map/monstrosity.cpp index b8a3fa3c795..9ac55f603f8 100644 --- a/src/map/monstrosity.cpp +++ b/src/map/monstrosity.cpp @@ -308,9 +308,9 @@ void monstrosity::HandleZoneIn(CCharEntity* PChar) // TODO: There are more conditions to handle here? if (PChar->loc.zone->GetID() != ZONE_FERETORY) { - uint32 duration = PChar->m_PMonstrosity->Belligerency ? 60 : 64800 /* 18 hours */; + auto duration = PChar->m_PMonstrosity->Belligerency ? 1min : 18h; - CStatusEffect* PEffect = new CStatusEffect(EFFECT::EFFECT_GESTATION, EFFECT::EFFECT_GESTATION, 0, 0, duration); + CStatusEffect* PEffect = new CStatusEffect(EFFECT::EFFECT_GESTATION, EFFECT::EFFECT_GESTATION, 0, 0s, duration); // TODO: Move these into the db PEffect->AddEffectFlag(EFFECTFLAG_INVISIBLE); @@ -616,7 +616,7 @@ void monstrosity::HandleDeathMenu(CCharEntity* PChar, uint8 type) PChar->loc.p.y = 0.0f; PChar->loc.p.z = 0.0f; - PChar->SetDeathTimestamp(0); + PChar->SetDeathTime(timer::time_point::min()); PChar->status = STATUS_TYPE::DISAPPEAR; diff --git a/src/map/navmesh.cpp b/src/map/navmesh.cpp index 006ff30e6f1..fded1d51444 100644 --- a/src/map/navmesh.cpp +++ b/src/map/navmesh.cpp @@ -401,7 +401,7 @@ auto CNavMesh::findPath(const position_t& start, const position_t& end) -> std:: CNavMesh::ToFFXIPos(pathPos); - outPoints.emplace_back(pathpoint_t{ { pathPos[0], pathPos[1], pathPos[2], 0, 0 }, 0, false }); + outPoints.emplace_back(pathpoint_t{ { pathPos[0], pathPos[1], pathPos[2], 0, 0 }, 0s, false }); } return outPoints; diff --git a/src/map/packet_guard.cpp b/src/map/packet_guard.cpp index 6d656c8eaff..60f300c1121 100644 --- a/src/map/packet_guard.cpp +++ b/src/map/packet_guard.cpp @@ -21,6 +21,8 @@ #include "packet_guard.h" +#include "common/timer.h" + // #define PACKETGUARD_CAP_ENABLED 1 #include // Lookup @@ -38,7 +40,7 @@ namespace PacketGuard std::unordered_map> allowList; // Time in seconds (double) - std::unordered_map ratelimitList; // Default will be 0 - No Limit + std::unordered_map ratelimitList; void Init() { @@ -80,13 +82,13 @@ namespace PacketGuard // NOTE: You should rate limit any packet that a player can // : send at will that results in an immediate database hit // : or generates logs or results in file or network io. - ratelimitList[0x017] = 1.0; // Invalid NPC Information Response - ratelimitList[0x03B] = 1.0; // Mannequin Equip - ratelimitList[0x05D] = 2.0; // Emotes - ratelimitList[0x0F4] = 1.0; // Wide Scan - ratelimitList[0x0F5] = 1.0; // Wide Scan Track - ratelimitList[0x11B] = 2.0; // Set Job Master Display - ratelimitList[0x11D] = 2.0; // Jump + ratelimitList[0x017] = 1s; // Invalid NPC Information Response + ratelimitList[0x03B] = 1s; // Mannequin Equip + ratelimitList[0x05D] = 2s; // Emotes + ratelimitList[0x0F4] = 1s; // Wide Scan + ratelimitList[0x0F5] = 1s; // Wide Scan Track + ratelimitList[0x11B] = 2s; // Set Job Master Display + ratelimitList[0x11D] = 2s; // Jump } bool PacketIsValidForPlayerState(CCharEntity* PChar, uint16 SmallPD_Type) @@ -112,20 +114,19 @@ namespace PacketGuard bool IsRateLimitedPacket(CCharEntity* PChar, uint16 SmallPD_Type) { TracyZoneScoped; - using namespace std::chrono; - - double lastPacketRecievedTime = static_cast(PChar->m_PacketRecievedTimestamps[SmallPD_Type]); - double timeNowSeconds = static_cast(time_point_cast(server_clock::now()).time_since_epoch().count()); - double ratelimitTime = ratelimitList[SmallPD_Type]; + auto timeNow = timer::now(); + auto lastPacketRecieved = PChar->m_PacketRecievedTimestamps.emplace(SmallPD_Type, timeNow); - PChar->m_PacketRecievedTimestamps[SmallPD_Type] = timeNowSeconds; - - if (lastPacketRecievedTime == 0 || ratelimitTime == 0) + if (lastPacketRecieved.second || ratelimitList.count(SmallPD_Type) == 0) { return false; } + auto lastPacketRecievedTime = lastPacketRecieved.first->second; + auto ratelimitTime = ratelimitList[SmallPD_Type]; + + PChar->m_PacketRecievedTimestamps[SmallPD_Type] = timeNow; - return timeNowSeconds - lastPacketRecievedTime < ratelimitList[SmallPD_Type]; + return timeNow < lastPacketRecievedTime + ratelimitTime; } bool PacketsArrivingInCorrectOrder(CCharEntity* PChar, uint16 SmallPD_Type) diff --git a/src/map/packet_system.cpp b/src/map/packet_system.cpp index 5664f862ff0..7f5bd52f404 100644 --- a/src/map/packet_system.cpp +++ b/src/map/packet_system.cpp @@ -1060,7 +1060,7 @@ void SmallPacket0x01A(MapSession* const PSession, CCharEntity* const PChar, CBas } else if (charutils::hasKeyItem(PChar, 3072 + MountID)) { - if (PChar->PRecastContainer->HasRecast(RECAST_ABILITY, 256, 60)) + if (PChar->PRecastContainer->HasRecast(RECAST_ABILITY, 256, 60s)) { PChar->pushPacket(PChar, PChar, 0, 0, 94); @@ -1079,13 +1079,13 @@ void SmallPacket0x01A(MapSession* const PSession, CCharEntity* const PChar, CBas EFFECT_MOUNTED, EFFECT_MOUNTED, MountID ? ++MountID : 0, - 0, - 1800, + 0s, + 30min, 0, 0x40), // previously known as nameflag "FLAG_CHOCOBO" EffectNotice::Silent); - PChar->PRecastContainer->Add(RECAST_ABILITY, 256, 60); + PChar->PRecastContainer->Add(RECAST_ABILITY, 256, 60s); PChar->pushPacket(PChar); luautils::OnPlayerMount(PChar); @@ -1501,8 +1501,9 @@ void SmallPacket0x032(MapSession* const PSession, CCharEntity* const PChar, CBas return; } - auto lastTargetTradeTimeSeconds = std::chrono::duration_cast(server_clock::now() - PTarget->lastTradeInvite).count(); - if ((PTarget->TradePending.targid != 0 && lastTargetTradeTimeSeconds < 60) || PTarget->UContainer->GetType() == UCONTAINER_TRADE) + timer::time_point currentTime = timer::now(); + auto lastTargetTrade = currentTime - PTarget->lastTradeInvite; + if ((PTarget->TradePending.targid != 0 && lastTargetTrade < 60s) || PTarget->UContainer->GetType() == UCONTAINER_TRADE) { // Can't trade with someone who's already got a pending trade before timeout PChar->pushPacket(PTarget, 0x07); @@ -1527,11 +1528,11 @@ void SmallPacket0x032(MapSession* const PSession, CCharEntity* const PChar, CBas } } - PChar->lastTradeInvite = server_clock::now(); + PChar->lastTradeInvite = currentTime; PChar->TradePending.id = charid; PChar->TradePending.targid = targid; - PTarget->lastTradeInvite = server_clock::now(); + PTarget->lastTradeInvite = currentTime; PTarget->TradePending.id = PChar->id; PTarget->TradePending.targid = PChar->targid; PTarget->pushPacket(PChar); @@ -1739,7 +1740,7 @@ void SmallPacket0x034(MapSession* const PSession, CCharEntity* const PChar, CBas sender_name = PChar->getName(), receiver = PTarget->id, receiver_name = PTarget->getName(), - date = static_cast(time(nullptr))]() + date = earth_time::timestamp()]() { const auto query = "INSERT INTO audit_trade(itemid, quantity, sender, sender_name, receiver, receiver_name, date) VALUES (?, ?, ?, ?, ?, ?, ?)"; if (!db::preparedStmt(query, itemID, quantity, sender, sender_name, receiver, receiver_name, date)) @@ -1843,7 +1844,7 @@ void SmallPacket0x036(MapSession* const PSession, CCharEntity* const PChar, CBas sender_name = PChar->getName(), receiver = PNpc->id, receiver_name = PNpc->getName(), - date = static_cast(time(nullptr))]() + date = earth_time::timestamp()]() { const auto query = "INSERT INTO audit_trade(itemid, quantity, sender, sender_name, receiver, receiver_name, date) VALUES (?, ?, ?, ?, ?, ?, ?)"; if (!db::preparedStmt(query, itemID, quantity, sender, sender_name, receiver, receiver_name, date)) @@ -1927,7 +1928,7 @@ void SmallPacket0x03A(MapSession* const PSession, CCharEntity* const PChar, CBas uint8 size = PItemContainer->GetSize(); - if (gettick() - PItemContainer->LastSortingTime < 1000) + if (timer::now() < PItemContainer->LastSortingTime + 1s) { if (settings::get("map.LIGHTLUGGAGE_BLOCK") == (int32)(++PItemContainer->SortingPacket)) { @@ -1939,7 +1940,7 @@ void SmallPacket0x03A(MapSession* const PSession, CCharEntity* const PChar, CBas else { PItemContainer->SortingPacket = 0; - PItemContainer->LastSortingTime = gettick(); + PItemContainer->LastSortingTime = timer::now(); } for (uint8 slotID = 1; slotID <= size; ++slotID) { @@ -2351,7 +2352,7 @@ void SmallPacket0x04B(MapSession* const PSession, CCharEntity* const PChar, CBas selfEntry.race = PChar->mainlook.race; selfEntry.allegiance = static_cast(PChar->allegiance); selfEntry.fishRank = PChar->RealSkills.rank[SKILLTYPE::SKILL_FISHING]; - selfEntry.submitTime = CVanaTime::getInstance()->getVanaTime(); + selfEntry.submitTime = earth_time::vanadiel_timestamp(); } } @@ -4117,7 +4118,7 @@ void SmallPacket0x085(MapSession* const PSession, CCharEntity* const PChar, CBas seller_name = PChar->getName(), baseprice = PItem->getBasePrice(), totalprice = cost, - time = static_cast(time(nullptr))]() + time = earth_time::timestamp()]() { const auto query = "INSERT INTO audit_vendor(itemid, quantity, seller, seller_name, baseprice, totalprice, date) VALUES (?, ?, ?, ?, ?, ?, ?)"; if (!db::preparedStmt(query, itemid, quantity, seller, seller_name, baseprice, totalprice, time)) @@ -4161,7 +4162,7 @@ void SmallPacket0x096(MapSession* const PSession, CCharEntity* const PChar, CBas // Force full synth duration wait no matter the synth animation length // Thus players can synth on whatever fps they want - if (PChar->m_LastSynthTime + 15s > server_clock::now()) + if (PChar->m_LastSynthTime + 15s > timer::now()) { PChar->pushPacket(PChar, PChar, 0, 0, 94); return; @@ -4788,7 +4789,7 @@ void SmallPacket0x0B5(MapSession* const PSession, CCharEntity* const PChar, CBas else if (!isInYellCooldown) { // CharVar will self-expire and set to zero after the cooldown period - PChar->setCharVar("[YELL]Cooldown", 1, CVanaTime::getInstance()->getSysTime() + yellCooldownTime); + PChar->setCharVar("[YELL]Cooldown", 1, static_cast(earth_time::timestamp() + yellCooldownTime)); message::send(ipc::ChatMessageYell{ .senderId = PChar->id, @@ -5856,9 +5857,9 @@ void SmallPacket0x0E7(MapSession* const PSession, CCharEntity* const PChar, CBas if (PChar->PPet == nullptr || (PChar->PPet->m_EcoSystem != ECOSYSTEM::AVATAR && PChar->PPet->m_EcoSystem != ECOSYSTEM::ELEMENTAL)) { - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, settings::get("map.HEALING_TICK_DELAY"), 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, std::chrono::seconds(settings::get("map.HEALING_TICK_DELAY")), 0s)); } - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEAVEGAME, 0, ExitType, 5, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEAVEGAME, 0, ExitType, 5s, 0s)); } else if (PChar->animation == ANIMATION_HEALING) { @@ -5870,7 +5871,7 @@ void SmallPacket0x0E7(MapSession* const PSession, CCharEntity* const PChar, CBas { uint8 ExitType = (data.ref(0x06) == 1 ? 7 : 35); - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEAVEGAME, 0, ExitType, 5, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEAVEGAME, 0, ExitType, 5s, 0s)); } } } @@ -5912,7 +5913,7 @@ void SmallPacket0x0E8(MapSession* const PSession, CCharEntity* const PChar, CBas { PChar->PPet->PAI->Disengage(); } - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, settings::get("map.HEALING_TICK_DELAY"), 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HEALING, 0, 0, std::chrono::seconds(settings::get("map.HEALING_TICK_DELAY")), 0s)); return; } PChar->pushPacket(PChar, PChar, 0, 0, 345); @@ -6427,7 +6428,7 @@ void SmallPacket0x0FC(MapSession* const PSession, CCharEntity* const PChar, CBas PChar->pushPacket(itemID, 132); // "Your moogle plants the in the flowerpot." PPotItem->cleanPot(); PPotItem->setPlant(CItemFlowerpot::getPlantFromSeed(itemID)); - PPotItem->setPlantTimestamp(CVanaTime::getInstance()->getVanaTime()); + PPotItem->setPlantTimestamp(earth_time::vanadiel_timestamp()); PPotItem->setStrength(xirand::GetRandomNumber(33)); gardenutils::GrowToNextStage(PPotItem); updatedPot = true; @@ -6895,7 +6896,7 @@ void SmallPacket0x102(MapSession* const PSession, CCharEntity* const PChar, CBas auto* PSpell = spell::GetSpell(spellId); if (CBlueSpell* PBlueSpell = dynamic_cast(PSpell)) { - PChar->PRecastContainer->Add(RECAST_MAGIC, static_cast(PBlueSpell->getID()), 60); + PChar->PRecastContainer->Add(RECAST_MAGIC, static_cast(PBlueSpell->getID()), 60s); } } } @@ -7145,7 +7146,7 @@ void SmallPacket0x106(MapSession* const PSession, CCharEntity* const PChar, CBas purchaserID = PChar->id, purchaserName = PChar->getName(), price = PriceWithTax, - date = static_cast(time(nullptr))] + date = earth_time::timestamp()] { const auto query = "INSERT INTO audit_bazaar(itemid, quantity, seller, seller_name, purchaser, purchaser_name, price, date) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; if (!db::preparedStmt(query, itemID, quantity, sellerID, sellerName, purchaserID, purchaserName, price, date)) diff --git a/src/map/packets/action.cpp b/src/map/packets/action.cpp index 7a5912ee47e..469b5bff83a 100644 --- a/src/map/packets/action.cpp +++ b/src/map/packets/action.cpp @@ -91,7 +91,7 @@ CActionPacket::CActionPacket(action_t& action) case ACTION_JOBABILITY_FINISH: { packBitsBE(buffer_.data(), action.actionid, 86, 10); - packBitsBE(buffer_.data(), action.recast, 118, 10); + packBitsBE(buffer_.data(), timer::count_seconds(action.recast), 118, 10); } break; case ACTION_RUN_WARD_EFFUSION: @@ -250,12 +250,12 @@ CActionPacket::CActionPacket(action_t& action) { packBitsBE(buffer_.data(), action.actionid, 86, 10); // either this way or enumerate all recast timers and compare the spell id. - packBitsBE(buffer_.data(), action.recast, 118, 10); + packBitsBE(buffer_.data(), timer::count_seconds(action.recast), 118, 10); } break; case ACTION_MAGIC_INTERRUPT: { - packBitsBE(buffer_.data(), action.recast, 118, 16); + packBitsBE(buffer_.data(), timer::count_seconds(action.recast), 118, 16); // FourCC command "sp" - interrupt packBitsBE(buffer_.data(), 0x7073, 86, 16); diff --git a/src/map/packets/action.h b/src/map/packets/action.h index 9b219df4970..9ddac6663d7 100644 --- a/src/map/packets/action.h +++ b/src/map/packets/action.h @@ -129,7 +129,7 @@ struct action_t uint32 id; ACTIONTYPE actiontype; uint16 actionid; - uint16 recast; + timer::duration recast; SPELLGROUP spellgroup; std::vector actionLists; @@ -137,7 +137,7 @@ struct action_t : id(0) , actiontype(ACTION_NONE) , actionid(0) - , recast(0) + , recast(0s) , spellgroup(SPELLGROUP_NONE) { } diff --git a/src/map/packets/bazaar_item.cpp b/src/map/packets/bazaar_item.cpp index 564ab9b6aed..606b65dc5e2 100644 --- a/src/map/packets/bazaar_item.cpp +++ b/src/map/packets/bazaar_item.cpp @@ -44,15 +44,15 @@ CBazaarItemPacket::CBazaarItemPacket(CItem* PItem, uint8 SlotID, uint16 Tax) if (PItem->isSubType(ITEM_CHARGED) && PItem->isType(ITEM_USABLE)) { - uint32 currentTime = CVanaTime::getInstance()->getVanaTime(); - uint32 nextUseTime = ((CItemUsable*)PItem)->getLastUseTime() + ((CItemUsable*)PItem)->getReuseDelay(); + timer::time_point currentTime = timer::now(); + timer::time_point nextUseTime = static_cast(PItem)->getNextUseTime(); ref(0x11) = 0x01; // ITEM_CHARGED flag ref(0x12) = ((CItemUsable*)PItem)->getCurrentCharges(); ref(0x14) = (nextUseTime > currentTime ? 0x90 : 0xD0); - ref(0x15) = nextUseTime; - ref(0x19) = ((CItemUsable*)PItem)->getUseDelay() + currentTime; + ref(0x15) = earth_time::vanadiel_timestamp(timer::to_utc(nextUseTime)); + ref(0x19) = static_cast(timer::count_seconds(static_cast(PItem)->getUseDelay()) + earth_time::vanadiel_timestamp()); } else { diff --git a/src/map/packets/char_check.cpp b/src/map/packets/char_check.cpp index 998b5a53c30..3fbf9b3fd77 100644 --- a/src/map/packets/char_check.cpp +++ b/src/map/packets/char_check.cpp @@ -53,15 +53,15 @@ CCheckPacket::CCheckPacket(CCharEntity* PChar, CCharEntity* PTarget) if (PItem->isSubType(ITEM_CHARGED)) { - uint32 currentTime = CVanaTime::getInstance()->getVanaTime(); - uint32 nextUseTime = ((CItemUsable*)PItem)->getLastUseTime() + ((CItemUsable*)PItem)->getReuseDelay(); + timer::time_point currentTime = timer::now(); + timer::time_point nextUseTime = static_cast(PItem)->getNextUseTime(); ref(size * 2 + 0x04) = 0x01; ref(size * 2 + 0x05) = ((CItemUsable*)PItem)->getCurrentCharges(); ref(size * 2 + 0x07) = (nextUseTime > currentTime ? 0x90 : 0xD0); - ref(size * 2 + 0x08) = nextUseTime; - ref(size * 2 + 0x0C) = ((CItemUsable*)PItem)->getUseDelay() + currentTime; + ref(size * 2 + 0x08) = earth_time::vanadiel_timestamp(timer::to_utc(nextUseTime)); + ref(size * 2 + 0x0C) = static_cast(timer::count_seconds(static_cast(PItem)->getUseDelay()) + earth_time::vanadiel_timestamp()); } if (PItem->isSubType(ITEM_AUGMENTED)) diff --git a/src/map/packets/char_recast.cpp b/src/map/packets/char_recast.cpp index 1e80b6f782c..47c6a0f93a2 100644 --- a/src/map/packets/char_recast.cpp +++ b/src/map/packets/char_recast.cpp @@ -39,22 +39,22 @@ CCharRecastPacket::CCharRecastPacket(CCharEntity* PChar) for (auto&& recast : *RecastList) { - uint32 recasttime = (recast.RecastTime == 0 ? 0 : ((recast.RecastTime - (uint32)(time(nullptr) - recast.TimeStamp)))); + uint32 recastSeconds = static_cast(timer::count_seconds(recast.RecastTime == 0s ? 0s : (recast.TimeStamp - timer::now() + recast.RecastTime))); if (recast.ID == 256) // borrowing this id for mount recast { - ref(0xFC) = recasttime; + ref(0xFC) = recastSeconds; ref(0xFE) = recast.ID; } else if (recast.ID != 0) { - ref(0x0C + count * 8) = recasttime; + ref(0x0C + count * 8) = recastSeconds; ref(0x0F + count * 8) = (uint8)recast.ID; count++; } else { - ref(0x04) = recasttime; // 2h ability (recast id is 0) + ref(0x04) = recastSeconds; // 2h ability (recast id is 0) } // Retail currently only allows 31 distinct recasts to be sent in the packet diff --git a/src/map/packets/char_status.cpp b/src/map/packets/char_status.cpp index 2f558d17499..d61fa1c1648 100644 --- a/src/map/packets/char_status.cpp +++ b/src/map/packets/char_status.cpp @@ -227,8 +227,11 @@ CCharStatusPacket::CCharStatusPacket(CCharEntity* PChar) packet->b = (LSColor.B << 4) + 15; } - packet->dead_counter1 = PChar->GetTimeRemainingUntilDeathHomepoint(); - packet->dead_counter2 = CVanaTime::getInstance()->getVanaTime() + packet->dead_counter1 / 60; + // The client uses 66min as the maximum amount of time for death + // Once this value reaches below 6min then the client will force homepoint the character + auto deadRemaining = timer::count_seconds(6min + PChar->GetTimeUntilDeathHomepoint()); + packet->dead_counter1 = static_cast(60 * deadRemaining); + packet->dead_counter2 = earth_time::vanadiel_timestamp() + deadRemaining; packet->costume_id = PChar->m_Costume; packet->model_hitbox_size = 4; // TODO: verify this packet->mount_id = 0; diff --git a/src/map/packets/conquest_map.cpp b/src/map/packets/conquest_map.cpp index f03f43a4ab9..c43c99caaa7 100644 --- a/src/map/packets/conquest_map.cpp +++ b/src/map/packets/conquest_map.cpp @@ -75,7 +75,7 @@ CConquestPacket::CConquestPacket(CCharEntity* PChar) ref(0x04) = conquest::GetBalance(sandoria_regions, bastok_regions, windurst_regions, sandoria_prev, bastok_prev, windurst_prev); ref(0x05) = conquest::GetAlliance(sandoria_regions, bastok_regions, windurst_regions, sandoria_prev, bastok_prev, windurst_prev); - ref(0x8C) = conquest::GetNexTally(); + ref(0x8C) = conquest::GetNextTally(); ref(0x90) = charutils::GetPoints(PChar, charutils::GetConquestPointsName(PChar).c_str()); ref(0x9C) = 0x01; diff --git a/src/map/packets/fish_ranking.cpp b/src/map/packets/fish_ranking.cpp index 9e7c759f67d..b1d9c627b3b 100644 --- a/src/map/packets/fish_ranking.cpp +++ b/src/map/packets/fish_ranking.cpp @@ -36,7 +36,7 @@ CFishRankingPacket::CFishRankingPacket(const std::vector& e ref(0x05) = 1; ref(0x06) = 2; // 1 = Svr Message, 2 = Fishing Rank. Packets otherwise identical. ref(0x07) = language; - ref(0x08) = (timestamp == 0 ? CVanaTime::getInstance()->getSysTime() : timestamp); + ref(0x08) = (timestamp == 0 ? earth_time::timestamp() : timestamp); ref(0x0C) = 0; // Message Length (Total) ref(0x10) = 0; // Message Offset ref(0x14) = 0; // Message Length diff --git a/src/map/packets/inventory_item.cpp b/src/map/packets/inventory_item.cpp index fe728d47b87..23fdca10504 100644 --- a/src/map/packets/inventory_item.cpp +++ b/src/map/packets/inventory_item.cpp @@ -55,18 +55,17 @@ CInventoryItemPacket::CInventoryItemPacket(CItem* PItem, uint8 LocationID, uint8 if (((CItemUsable*)PItem)->getCurrentCharges() > 0) { - if (((CItemUsable*)PItem)->getReuseTime() == 0) + if (((CItemUsable*)PItem)->getReuseTime() == 0s) { flags |= 0x40; // Ready to use } else { - uint32 CurrentTime = CVanaTime::getInstance()->getVanaTime(); - ref(0x15) = ((CItemUsable*)PItem)->getNextUseTime(); + timer::time_point nextUseTime = static_cast(PItem)->getNextUseTime(); + ref(0x15) = earth_time::vanadiel_timestamp(timer::to_utc(nextUseTime)); // Not sent if the item is unequipped. - - ref(0x19) = ((CItemUsable*)PItem)->getUseDelay() + CurrentTime; + ref(0x19) = static_cast(timer::count_seconds(static_cast(PItem)->getUseDelay()) + earth_time::vanadiel_timestamp()); } } else diff --git a/src/map/packets/objective_utility.cpp b/src/map/packets/objective_utility.cpp index ee12447eaca..9854096d0e7 100644 --- a/src/map/packets/objective_utility.cpp +++ b/src/map/packets/objective_utility.cpp @@ -40,7 +40,7 @@ CObjectiveUtilityPacket::CObjectiveUtilityPacket(uint32 duration, uint32 warning void CObjectiveUtilityPacket::addCountdown(uint32 duration, uint32 warning /* = 0 */) { ref(0x04) = ref(0x04) == 0 ? 0x01 : ref(0x04); - ref(0x08) = CVanaTime::getInstance()->getVanaTime(); + ref(0x08) = earth_time::vanadiel_timestamp(); ref(0x0C) = duration; ref(0x10) = warning; // If 0, defaults to 60. ref(0x24) |= OBJECTIVEUTILITY_COUNTDOWN; diff --git a/src/map/packets/roe_sparkupdate.cpp b/src/map/packets/roe_sparkupdate.cpp index 63b57a2c9b1..c56f882ee96 100644 --- a/src/map/packets/roe_sparkupdate.cpp +++ b/src/map/packets/roe_sparkupdate.cpp @@ -32,9 +32,9 @@ CRoeSparkUpdatePacket::CRoeSparkUpdatePacket(CCharEntity* PChar) this->setType(0x110); this->setSize(0x14); - uint32 vanaTime = CVanaTime::getInstance()->getVanaTime(); - uint32 daysSinceEpoch = vanaTime / (60 * 60 * 24); - uint32 weeksSinceEpoch = daysSinceEpoch / 7; + earth_time::duration vanaTime = std::chrono::seconds(earth_time::vanadiel_timestamp()); + uint32 daysSinceEpoch = std::chrono::floor(vanaTime).count(); + uint32 weeksSinceEpoch = std::chrono::floor(vanaTime).count(); const auto rset = db::preparedStmt("SELECT spark_of_eminence, deeds, plaudits FROM char_points WHERE charid = ? LIMIT 1", PChar->id); if (rset && rset->rowsCount() && rset->next()) diff --git a/src/map/packets/server_message.cpp b/src/map/packets/server_message.cpp index 6ae7d0269ed..b80c8728bb1 100644 --- a/src/map/packets/server_message.cpp +++ b/src/map/packets/server_message.cpp @@ -32,7 +32,7 @@ CServerMessagePacket::CServerMessagePacket(const std::string& message, int8 lang ref(0x05) = 1; ref(0x06) = 1; ref(0x07) = language; - ref(0x08) = (uint32)(timestamp == 0 ? time(nullptr) : timestamp); + ref(0x08) = static_cast(timestamp == 0 ? earth_time::timestamp() : timestamp); ref(0x0C) = 0; // Message Length (Total) ref(0x10) = 0; // Message Offset ref(0x14) = 0; // Message Length diff --git a/src/map/packets/status_effects.cpp b/src/map/packets/status_effects.cpp index 12fe0f3ef4e..87ff9da980b 100644 --- a/src/map/packets/status_effects.cpp +++ b/src/map/packets/status_effects.cpp @@ -41,16 +41,16 @@ CStatusEffectPacket::CStatusEffectPacket(CCharEntity* PChar) { if (PEffect->GetIcon() != 0) { + auto durationRemaining = 0x7FFFFFFF; + if (PEffect->GetDuration() > 0s && !PEffect->HasEffectFlag(EFFECTFLAG_HIDE_TIMER)) + { + // this value overflows, but the client expects the overflowed timestamp and corrects it + durationRemaining = timer::count_seconds(PEffect->GetStartTime() - timer::now() + PEffect->GetDuration()); + durationRemaining += earth_time::vanadiel_timestamp(); + durationRemaining *= 60; + } ref(0x08 + (i * 0x02)) = PEffect->GetIcon(); - // this value overflows, but the client expects the overflowed timestamp and corrects it - ref(0x48 + (i * 0x04)) = - PEffect->GetDuration() == 0 || (PEffect->HasEffectFlag(EFFECTFLAG_HIDE_TIMER)) - ? 0x7FFFFFFF - : (((PEffect->GetDuration() - - (uint32)std::chrono::duration_cast(server_clock::now() - PEffect->GetStartTime()).count()) / - 1000) + - CVanaTime::getInstance()->getVanaTime()) * - 60; + ref(0x48 + (i * 0x04)) = durationRemaining; ++i; } }); diff --git a/src/map/packets/treasure_find_item.cpp b/src/map/packets/treasure_find_item.cpp index f1f5b343859..0964a8b7de8 100644 --- a/src/map/packets/treasure_find_item.cpp +++ b/src/map/packets/treasure_find_item.cpp @@ -35,7 +35,7 @@ CTreasureFindItemPacket::CTreasureFindItemPacket(TreasurePoolItem* PItem, CBaseE ref(0x10) = PItem->ID; // Item ID ref(0x14) = PItem->SlotID; // Treasure Pool Slot ref(0x15) = isOldItem ? 1 : 0; // Old Item - ref(0x18) = (uint32)std::chrono::duration_cast(PItem->TimeStamp - get_server_start_time()).count(); + ref(0x18) = static_cast(timer::count_milliseconds(PItem->TimeStamp - timer::start_time)); if (PEntity != nullptr) { diff --git a/src/map/packets/zone_in.cpp b/src/map/packets/zone_in.cpp index bdb733f6a4c..673073e6df3 100644 --- a/src/map/packets/zone_in.cpp +++ b/src/map/packets/zone_in.cpp @@ -333,16 +333,18 @@ CZoneInPacket::CZoneInPacket(CCharEntity* PChar, const EventInfo* currentEvent) auto const& nameStr = PChar->getName(); std::memcpy(buffer_.data() + 0x84, nameStr.data(), nameStr.size()); - ref(0xA0) = PChar->GetPlayTime(); // time spent by the character in the game from the moment of creation + ref(0xA0) = static_cast(timer::count_seconds(PChar->GetPlayTime())); // time spent by the character in the game from the moment of creation ref(0xAE) = GetMogHouseLeavingFlag(PChar); - uint32 pktTime = CVanaTime::getInstance()->getVanaTime(); + auto currentTime = earth_time::now(); + ref(0x38) = earth_time::timestamp(currentTime); + ref(0x3C) = earth_time::vanadiel_timestamp(currentTime); - ref(0x38) = pktTime + VTIME_BASEDATE; - ref(0x3C) = pktTime; - - ref(0xA4) = PChar->GetTimeRemainingUntilDeathHomepoint(); + // The client uses 66min as the maximum amount of time for death + // Once this value reaches below 6min then the client will force homepoint the character + auto deadRemaining = timer::count_seconds(6min + PChar->GetTimeUntilDeathHomepoint()); + ref(0xA4) = static_cast(60 * deadRemaining); ref(0xB4) = PChar->GetMJob(); ref(0xB7) = PChar->GetSJob(); diff --git a/src/map/party.cpp b/src/map/party.cpp index 42814e06662..d8bd59fed3a 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -148,11 +148,11 @@ void CParty::DisbandParty(bool playerInitiated) PChar->PTreasurePool->updatePool(PChar); } CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, 30, MsgStd::LevelSyncRemoveLeftParty); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } db::preparedStmt("DELETE FROM accounts_parties WHERE charid = ?", PChar->id); @@ -316,11 +316,11 @@ void CParty::RemoveMember(CBattleEntity* PEntity) { SetSyncTarget("", MsgStd::LevelSyncRemoveLeftParty); CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, 30, MsgStd::LevelSyncRemoveLeftParty); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } DisableSync(); } @@ -329,11 +329,11 @@ void CParty::RemoveMember(CBattleEntity* PEntity) if (PChar->status != STATUS_TYPE::DISAPPEAR) { CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, 30, MsgStd::LevelSyncRemoveLeftParty); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } } } @@ -413,11 +413,11 @@ void CParty::DelMember(CBattleEntity* PEntity) { SetSyncTarget("", MsgStd::LevelSyncRemoveLeftParty); CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, 30, MsgStd::LevelSyncRemoveLeftParty); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } DisableSync(); } @@ -426,11 +426,11 @@ void CParty::DelMember(CBattleEntity* PEntity) if (PChar->status != STATUS_TYPE::DISAPPEAR) { CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, 30, MsgStd::LevelSyncRemoveLeftParty); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } } } @@ -610,7 +610,7 @@ void CParty::AddMember(CBattleEntity* PEntity) if (PLeader) { - PLeader->m_LeaderCreatedPartyTime = server_clock::now(); + PLeader->m_LeaderCreatedPartyTime = timer::now(); } } @@ -669,7 +669,7 @@ void CParty::AddMember(CBattleEntity* PEntity) if (PChar->getZone() == m_PSyncTarget->getZone()) { PChar->pushPacket(PChar, PChar, 0, m_PSyncTarget->GetMLevel(), MsgStd::LevelSyncActivated); - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, m_PSyncTarget->GetMLevel(), 0, 0), EffectNotice::Silent); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, m_PSyncTarget->GetMLevel(), 0s, 0s), EffectNotice::Silent); PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE | EFFECTFLAG_ON_ZONE); PChar->loc.zone->PushPacket(PChar, CHAR_INRANGE, std::make_unique(PChar)); } @@ -1137,7 +1137,7 @@ void CParty::SetSyncTarget(const std::string& MemberName, MsgStd message) if (member->status != STATUS_TYPE::DISAPPEAR && member->getZone() == PChar->getZone()) { member->pushPacket(PChar->GetMLevel(), 0, 0, 0, message); - member->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PChar->GetMLevel(), 0, 0), EffectNotice::Silent); + member->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PChar->GetMLevel(), 0s, 0s), EffectNotice::Silent); member->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE | EFFECTFLAG_ON_ZONE); member->loc.zone->PushPacket(member, CHAR_INRANGE, std::make_unique(member)); } @@ -1165,11 +1165,11 @@ void CParty::SetSyncTarget(const std::string& MemberName, MsgStd message) if (member->status != STATUS_TYPE::DISAPPEAR) { CStatusEffect* sync = member->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); - if (sync && sync->GetDuration() == 0) + if (sync && sync->GetDuration() == 0s) { member->pushPacket(member, member, 0, 30, message); - sync->SetStartTime(server_clock::now()); - sync->SetDuration(30000); + sync->SetStartTime(timer::now()); + sync->SetDuration(30s); } } } @@ -1356,17 +1356,17 @@ uint32 CParty::LoadPartySize() const return 0; } -uint32 CParty::GetTimeLastMemberJoined() +timer::time_point CParty::GetTimeLastMemberJoined() { auto* PLeader = dynamic_cast(CParty::GetLeader()); - auto LeaderMemberLastJoinedTime = server_clock::now(); + auto LeaderMemberLastJoinedTime = timer::now(); if (PLeader) { LeaderMemberLastJoinedTime = PLeader->m_LeaderCreatedPartyTime; } - return (uint32)std::chrono::time_point_cast(LeaderMemberLastJoinedTime).time_since_epoch().count(); + return LeaderMemberLastJoinedTime; } bool CParty::HasTrusts() diff --git a/src/map/party.h b/src/map/party.h index c4af962a9af..97e2a7ea132 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -95,8 +95,8 @@ class CParty bool IsFull() const; uint32 LoadPartySize() const; - uint32 GetTimeLastMemberJoined(); - bool HasTrusts(); + timer::time_point GetTimeLastMemberJoined(); + bool HasTrusts(); std::size_t GetMemberCountAcrossAllProcesses(); diff --git a/src/map/pch.h b/src/map/pch.h index 6465196bba2..e1b0ed505bd 100644 --- a/src/map/pch.h +++ b/src/map/pch.h @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include diff --git a/src/map/petskill.cpp b/src/map/petskill.cpp index 30c36042ab4..904d0b0efd6 100644 --- a/src/map/petskill.cpp +++ b/src/map/petskill.cpp @@ -27,8 +27,8 @@ CPetSkill::CPetSkill(uint16 id) , m_AnimID(0) , m_Aoe(0) , m_Distance(0) -, m_AnimationTime(0) -, m_ActivationTime(0) +, m_AnimationTime(0s) +, m_ActivationTime(0s) , m_ValidTarget(0) , m_Message(0) , m_Flag(0) @@ -154,12 +154,12 @@ void CPetSkill::setHPP(uint8 hpp) m_HPP = hpp; } -void CPetSkill::setAnimationTime(uint16 AnimationTime) +void CPetSkill::setAnimationTime(timer::duration AnimationTime) { m_AnimationTime = AnimationTime; } -void CPetSkill::setActivationTime(uint16 ActivationTime) +void CPetSkill::setActivationTime(timer::duration ActivationTime) { m_ActivationTime = ActivationTime; } @@ -314,12 +314,12 @@ uint16 CPetSkill::getValidTargets() const return m_ValidTarget; } -uint16 CPetSkill::getAnimationTime() const +timer::duration CPetSkill::getAnimationTime() const { return m_AnimationTime; } -uint16 CPetSkill::getActivationTime() const +timer::duration CPetSkill::getActivationTime() const { return m_ActivationTime; } diff --git a/src/map/petskill.h b/src/map/petskill.h index 67f8bd09106..79a9c00d1ff 100644 --- a/src/map/petskill.h +++ b/src/map/petskill.h @@ -39,28 +39,28 @@ class CPetSkill bool isBloodPactWard() const; bool isBloodPactRage() const; - uint16 getID() const; - uint16 getAnimationID() const; - uint8 getAoe() const; - float getDistance() const; - uint8 getFlag() const; - uint16 getAnimationTime() const; - uint16 getActivationTime() const; - uint16 getMsg() const; - uint8 getSkillFinishCategory() const; - uint16 getAoEMsg() const; - uint16 getValidTargets() const; - int16 getTP() const; - uint8 getHPP() const; - uint16 getTotalTargets() const; - uint32 getPrimaryTargetID() const; - uint16 getMsgForAction() const; - float getRadius() const; - int16 getParam() const; - uint8 getKnockback() const; - uint8 getPrimarySkillchain() const; - uint8 getSecondarySkillchain() const; - uint8 getTertiarySkillchain() const; + uint16 getID() const; + uint16 getAnimationID() const; + uint8 getAoe() const; + float getDistance() const; + uint8 getFlag() const; + timer::duration getAnimationTime() const; + timer::duration getActivationTime() const; + uint16 getMsg() const; + uint8 getSkillFinishCategory() const; + uint16 getAoEMsg() const; + uint16 getValidTargets() const; + int16 getTP() const; + uint8 getHPP() const; + uint16 getTotalTargets() const; + uint32 getPrimaryTargetID() const; + uint16 getMsgForAction() const; + float getRadius() const; + int16 getParam() const; + uint8 getKnockback() const; + uint8 getPrimarySkillchain() const; + uint8 getSecondarySkillchain() const; + uint8 getTertiarySkillchain() const; bool isDamageMsg() const; @@ -69,8 +69,8 @@ class CPetSkill void setAoe(uint8 aoe); void setDistance(float distance); void setFlag(uint8 flag); - void setAnimationTime(uint16 AnimationTime); - void setActivationTime(uint16 ActivationTime); + void setAnimationTime(timer::duration AnimationTime); + void setActivationTime(timer::duration ActivationTime); void setMsg(uint16 msg); void setSkillFinishCategory(uint8 category); void setValidTargets(uint16 targ); @@ -88,22 +88,22 @@ class CPetSkill void setName(const std::string& name); private: - uint16 m_ID; - uint16 m_AnimID; // animation id - std::string m_name; - uint8 m_Aoe; - float m_Distance; - uint16 m_AnimationTime; // how long the tp animation lasts for in ms - uint16 m_ActivationTime; // how long the pet prepares the tp move for - uint16 m_ValidTarget; - uint16 m_Message; // message param, scripters can edit this depending on self/resist/etc. - uint8 m_Flag; - int16 m_Param; - uint8 m_SkillFinishCategory; - uint8 m_knockback; // knockback value (0-7) - uint8 m_primarySkillchain; // weaponskill ID of skillchain properties - uint8 m_secondarySkillchain; - uint8 m_tertiarySkillchain; + uint16 m_ID; + uint16 m_AnimID; // animation id + std::string m_name; + uint8 m_Aoe; + float m_Distance; + timer::duration m_AnimationTime; // how long the tp animation lasts + timer::duration m_ActivationTime; // how long the pet prepares the tp move for + uint16 m_ValidTarget; + uint16 m_Message; // message param, scripters can edit this depending on self/resist/etc. + uint8 m_Flag; + int16 m_Param; + uint8 m_SkillFinishCategory; + uint8 m_knockback; // knockback value (0-7) + uint8 m_primarySkillchain; // weaponskill ID of skillchain properties + uint8 m_secondarySkillchain; + uint8 m_tertiarySkillchain; int16 m_TP; // the tp at the time of finish readying (for scripts) uint8 m_HPP; // HPP at the time of using mob skill (for scripts) diff --git a/src/map/recast_container.cpp b/src/map/recast_container.cpp index 0c7f9887a3a..bba1a0e54f6 100644 --- a/src/map/recast_container.cpp +++ b/src/map/recast_container.cpp @@ -81,23 +81,23 @@ Recast_t* CRecastContainer::GetRecast(RECASTTYPE type, uint16 id) * * ************************************************************************/ -void CRecastContainer::Add(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime, uint8 maxCharges) +void CRecastContainer::Add(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime, uint8 maxCharges) { Load(type, id, duration, chargeTime, maxCharges); } -Recast_t* CRecastContainer::Load(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime, uint8 maxCharges) +Recast_t* CRecastContainer::Load(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime, uint8 maxCharges) { Recast_t* recast = GetRecast(type, id); if (recast == nullptr) { - GetRecastList(type)->emplace_back(Recast_t{ id, time(nullptr), duration, chargeTime, maxCharges }); + GetRecastList(type)->emplace_back(Recast_t{ id, timer::now(), duration, chargeTime, maxCharges }); return &GetRecastList(type)->back(); } else { - if (chargeTime) + if (chargeTime != 0s) { recast->chargeTime = chargeTime; } @@ -105,16 +105,16 @@ Recast_t* CRecastContainer::Load(RECASTTYPE type, uint16 id, uint32 duration, ui { recast->maxCharges = maxCharges; } - if (recast->chargeTime == 0) + if (recast->chargeTime == 0s) { - recast->TimeStamp = time(nullptr); + recast->TimeStamp = timer::now(); recast->RecastTime = duration; } else { - if (recast->RecastTime == 0) + if (recast->RecastTime == 0s) { - recast->TimeStamp = time(nullptr); + recast->TimeStamp = timer::now(); } else if (recast->RecastTime + duration > recast->chargeTime * recast->maxCharges) { @@ -141,7 +141,7 @@ void CRecastContainer::Del(RECASTTYPE type) { for (auto&& recast : *PRecastList) { - recast.RecastTime = 0; + recast.RecastTime = 0s; } } else @@ -164,7 +164,7 @@ void CRecastContainer::Del(RECASTTYPE type, uint16 id) { if (auto* recast = GetRecast(RECAST_ABILITY, id)) { - recast->RecastTime = 0; + recast->RecastTime = 0s; } } else @@ -186,7 +186,7 @@ void CRecastContainer::DeleteByIndex(RECASTTYPE type, uint8 index) RecastList_t* PRecastList = GetRecastList(type); if (type == RECAST_ABILITY) { - PRecastList->at(index).RecastTime = 0; + PRecastList->at(index).RecastTime = 0s; } else { @@ -220,28 +220,35 @@ bool CRecastContainer::Has(RECASTTYPE type, uint16 id) * * ************************************************************************/ -bool CRecastContainer::HasRecast(RECASTTYPE type, uint16 id, uint32 recast) +bool CRecastContainer::HasRecast(RECASTTYPE type, uint16 id, timer::duration recast) { RecastList_t* PRecastList = GetRecastList(type); for (auto& i : *PRecastList) { - if (i.ID == id && i.RecastTime > 0) + if (i.ID == id && i.RecastTime > 0s) { - if (i.chargeTime == 0) + if (i.chargeTime == 0s) { return true; } else { // a request to use more charges than the maximum only applies to abilities who share normal recasts with charges (ie. sic) - if (recast > i.maxCharges) + // TODO: this is bad + // "recast" 1-4 = sic/ready + // "recast" 1 = quickdraw, stratagems + auto crypticRecastSecondsAsType = timer::count_seconds(recast); + if (crypticRecastSecondsAsType > i.maxCharges) { return true; } - auto charges = i.maxCharges - ((i.RecastTime - (uint32)(time(nullptr) - i.TimeStamp)) / (i.chargeTime)) - 1; - if (charges < recast) + auto currentRecast = i.TimeStamp - timer::now() + i.RecastTime; + uint8 availableCharges = static_cast(currentRecast / i.chargeTime); + auto charges = i.maxCharges - availableCharges - 1; + + if (charges < crypticRecastSecondsAsType) { return true; } @@ -268,7 +275,7 @@ void CRecastContainer::Check() { Recast_t* recast = &PRecastList->at(i); - if (time(nullptr) >= (recast->TimeStamp + recast->RecastTime)) + if (timer::now() >= recast->TimeStamp + recast->RecastTime) { if (type == RECAST_MAGIC) { @@ -276,7 +283,7 @@ void CRecastContainer::Check() } else { - recast->RecastTime = 0; + recast->RecastTime = 0s; } } } @@ -297,7 +304,7 @@ void CRecastContainer::ResetAbilities() { if (recast.ID != 0) { - Load(RECAST_ABILITY, recast.ID, 0); + Load(RECAST_ABILITY, recast.ID, 0s); } } } diff --git a/src/map/recast_container.h b/src/map/recast_container.h index 9db8173a14d..c74a9e651d7 100644 --- a/src/map/recast_container.h +++ b/src/map/recast_container.h @@ -23,6 +23,7 @@ #define _RECASTCONTAINER_H #include "common/cbasetypes.h" +#include "common/timer.h" #include @@ -37,11 +38,11 @@ enum RECASTTYPE struct Recast_t { - uint16 ID; - time_t TimeStamp; - uint32 RecastTime; - uint32 chargeTime; - uint8 maxCharges; + uint16 ID; + timer::time_point TimeStamp; + timer::duration RecastTime; + timer::duration chargeTime; + uint8 maxCharges; }; /************************************************************************ @@ -63,9 +64,9 @@ class CRecastContainer virtual void Del(RECASTTYPE type, uint16 id); virtual void DeleteByIndex(RECASTTYPE type, uint8 index); bool Has(RECASTTYPE type, uint16 id); - bool HasRecast(RECASTTYPE type, uint16 id, uint32 recast); - virtual void Add(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime = 0, uint8 maxCharges = 0); - Recast_t* Load(RECASTTYPE type, uint16 id, uint32 duration, uint32 chargeTime = 0, uint8 maxCharges = 0); + bool HasRecast(RECASTTYPE type, uint16 id, timer::duration recast); + virtual void Add(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime = 0s, uint8 maxCharges = 0); + Recast_t* Load(RECASTTYPE type, uint16 id, timer::duration duration, timer::duration chargeTime = 0s, uint8 maxCharges = 0); virtual void ResetAbilities(); virtual void ChangeJob() { diff --git a/src/map/roe.cpp b/src/map/roe.cpp index 5b52c3a3e71..de5823c0bf1 100644 --- a/src/map/roe.cpp +++ b/src/map/roe.cpp @@ -21,11 +21,7 @@ #include "roe.h" -#include "common/vana_time.h" - -#include - -#include "common/vana_time.h" +#include "common/timer.h" #include "lua/luautils.h" #include "packets/chat_message.h" #include "utils/charutils.h" @@ -36,7 +32,7 @@ #include "packets/roe_sparkupdate.h" #include "packets/roe_update.h" -#define ROE_CACHETIME 15 +#define ROE_CACHETIME 15s std::array RoeHandlers; RoeSystemData roeutils::RoeSystem; @@ -44,7 +40,7 @@ RoeSystemData roeutils::RoeSystem; void SaveEminenceDataNice(CCharEntity* PChar) { TracyZoneScoped; - if (PChar->m_eminenceCache.lastWriteout < time(nullptr) - ROE_CACHETIME) + if (PChar->m_eminenceCache.lastWriteout < timer::now() - ROE_CACHETIME) { charutils::SaveEminenceData(PChar); } @@ -451,38 +447,35 @@ namespace roeutils // Only chars with First Step Forward complete can get timed/daily records if (GetEminenceRecordCompletion(PChar, 1)) { - time_t lastOnline = PChar->lastOnline; - time_t lastJstMidnight = CVanaTime::getInstance()->getJstMidnight() - (60 * 60 * 24); // Unix timestamp of the last JST midnight + auto currentTime = earth_time::now(); + auto lastJstMidnight = earth_time::jst::get_next_midnight(currentTime) - 24h; // Most recent JST midnight { // Daily Reset - if (lastOnline < lastJstMidnight) + if (PChar->lastOnline < lastJstMidnight) { ClearDailyRecords(PChar); } } { // Weekly Reset - // Get the current JST DOTW (0-6), that plus 6 mod 7 will push the start of the week to Monday. - // Multiply that to get seconds, and subtract from last JST midnight. - uint32 jstWeekday = (CVanaTime::getInstance()->getJstWeekDay() + 6) % 7; - time_t lastJstWeeklyReset = lastJstMidnight - (jstWeekday * (60 * 60 * 24)); // Unix timestamp of last JST Midnight (Sunday->Monday) - time_t lastTwoJstResets = lastJstWeeklyReset - (7 * (60 * 60 * 24)); // Unix timestamp of two JST resets ago - - if (lastOnline < lastJstWeeklyReset) + auto lastWeeklyReset = earth_time::get_next_game_week(currentTime) - std::chrono::days(7); + if (PChar->lastOnline < lastWeeklyReset) { ClearWeeklyRecords(PChar); - if (lastOnline < lastTwoJstResets) + auto prevLastWeeklyReset = lastWeeklyReset - std::chrono::days(7); + if (PChar->lastOnline < prevLastWeeklyReset) { charutils::SetPoints(PChar, "prev_accolades", 0); } } } - { // 4hr Reset - time_t lastJstTimedBlock = lastJstMidnight + (static_cast(CVanaTime::getInstance()->getJstHour() / 4) * (60 * 60 * 4)); // Unix timestamp of the start of the current 4-hr block + { // 4hr Reset + uint8 currentBlock = static_cast(earth_time::jst::get_hour(currentTime) / 4); + auto lastJstTimedBlock = lastJstMidnight + std::chrono::hours(currentBlock * 4); // Start of the current 4-hr block - if (lastOnline < lastJstTimedBlock || PChar->m_eminenceLog.active[30] != GetActiveTimedRecord()) + if (PChar->lastOnline < lastJstTimedBlock || PChar->m_eminenceLog.active[30] != GetActiveTimedRecord()) { PChar->m_eminenceCache.notifyTimedRecord = static_cast(GetActiveTimedRecord()); AddActiveTimedRecord(PChar); @@ -515,8 +508,9 @@ namespace roeutils uint16 GetActiveTimedRecord() { TracyZoneScoped; - uint8 day = static_cast(CVanaTime::getInstance()->getJstWeekDay()); - uint8 block = static_cast(CVanaTime::getInstance()->getJstHour() / 4); + auto currentTime = earth_time::now(); + uint8 day = static_cast(earth_time::jst::get_weekday(currentTime)); + uint8 block = static_cast(earth_time::jst::get_hour(currentTime) / 4); return RoeSystem.TimedRecordTable[day][block]; } @@ -687,8 +681,6 @@ namespace roeutils const char* rankingQuery = "UPDATE unity_system SET members_prev = members_current, points_prev = points_current, members_current = 0, points_current = 0"; _sql->Query(rankingQuery); - - roeutils::UpdateUnityRankings(); } void UpdateUnityRankings() diff --git a/src/map/spell.cpp b/src/map/spell.cpp index 0b7ce6ed596..cc27f42265d 100644 --- a/src/map/spell.cpp +++ b/src/map/spell.cpp @@ -73,22 +73,22 @@ void CSpell::setJob(int8* jobs) std::memcpy(&m_job[1], jobs, 22); } -uint32 CSpell::getCastTime() const +timer::duration CSpell::getCastTime() const { return m_castTime; } -void CSpell::setCastTime(uint32 CastTime) +void CSpell::setCastTime(timer::duration CastTime) { m_castTime = CastTime; } -uint32 CSpell::getRecastTime() const +timer::duration CSpell::getRecastTime() const { return m_recastTime; } -void CSpell::setRecastTime(uint32 RecastTime) +void CSpell::setRecastTime(timer::duration RecastTime) { m_recastTime = RecastTime; } @@ -217,12 +217,12 @@ void CSpell::setAnimationID(uint16 AnimationID) m_animation = AnimationID; } -uint16 CSpell::getAnimationTime() const +timer::duration CSpell::getAnimationTime() const { return m_animationTime; } -void CSpell::setAnimationTime(uint16 AnimationTime) +void CSpell::setAnimationTime(timer::duration AnimationTime) { m_animationTime = AnimationTime; } @@ -377,12 +377,12 @@ int32 CSpell::getVE() const return m_VE; } -void CSpell::setModifiedRecast(uint32 mrec) +void CSpell::setModifiedRecast(timer::duration mrec) { m_modifiedRecastTime = mrec; } -uint32 CSpell::getModifiedRecast() const +timer::duration CSpell::getModifiedRecast() const { return m_modifiedRecastTime; } @@ -479,10 +479,10 @@ namespace spell PSpell->setSpellFamily((SPELLFAMILY)_sql->GetIntData(4)); PSpell->setValidTarget(_sql->GetIntData(5)); PSpell->setSkillType(_sql->GetIntData(6)); - PSpell->setCastTime(_sql->GetIntData(7)); - PSpell->setRecastTime(_sql->GetIntData(8)); + PSpell->setCastTime(std::chrono::milliseconds(_sql->GetIntData(7))); + PSpell->setRecastTime(std::chrono::milliseconds(_sql->GetIntData(8))); PSpell->setAnimationID(_sql->GetIntData(9)); - PSpell->setAnimationTime(_sql->GetIntData(10)); + PSpell->setAnimationTime(std::chrono::milliseconds(_sql->GetIntData(10))); PSpell->setMPCost(_sql->GetIntData(11)); PSpell->setAOE(_sql->GetIntData(12)); PSpell->setBase(_sql->GetIntData(13)); diff --git a/src/map/spell.h b/src/map/spell.h index 0bcc8b2b719..0022db99c21 100644 --- a/src/map/spell.h +++ b/src/map/spell.h @@ -1056,11 +1056,11 @@ class CSpell SpellID getID(); uint8 getJob(JOBTYPE JobID); uint16 getMPCost() const; - uint32 getCastTime() const; - uint32 getRecastTime() const; + timer::duration getCastTime() const; + timer::duration getRecastTime() const; uint16 getValidTarget() const; uint16 getAnimationID() const; - uint16 getAnimationTime() const; + timer::duration getAnimationTime() const; SPELLGROUP getSpellGroup(); SPELLFAMILY getSpellFamily(); uint8 getSkillType() const; @@ -1074,7 +1074,7 @@ class CSpell uint16 getMagicBurstMessage() const; int32 getCE() const; int32 getVE() const; - uint32 getModifiedRecast() const; + timer::duration getModifiedRecast() const; float getRadius() const; uint16 getAoEMessage() const; // returns the single target message for AoE moves uint8 getRequirements() const; @@ -1097,11 +1097,11 @@ class CSpell void setID(SpellID id); void setJob(int8* jobs); void setMPCost(uint16 MP); - void setCastTime(uint32 CastTime); - void setRecastTime(uint32 RecastTime); + void setCastTime(timer::duration CastTime); + void setRecastTime(timer::duration RecastTime); void setValidTarget(uint16 ValidTarget); void setAnimationID(uint16 AnimationID); - void setAnimationTime(uint16 AnimationTime); + void setAnimationTime(timer::duration AnimationTime); void setSpellGroup(SPELLGROUP SpellGroup); void setSpellFamily(SPELLFAMILY SpellFamily); void setSkillType(uint8 SkillType); @@ -1120,7 +1120,7 @@ class CSpell void setVE(int32 ve); void setRequirements(uint8 requirements); void setMeritId(uint16 meritId); - void setModifiedRecast(uint32 mrec); + void setModifiedRecast(timer::duration mrec); void setFlag(uint8 flag); void setContentTag(const std::string& contentTag); void setRange(float range); @@ -1133,37 +1133,37 @@ class CSpell CSpell& operator=(const CSpell&) = default; private: - SpellID m_ID; // spell id - uint32 m_primaryTargetID{}; // primary target ID - uint32 m_castTime{}; // time to cast spell - uint32 m_recastTime{}; // recast time - uint16 m_animation{}; // animation for spell - uint16 m_animationTime{}; - uint8 m_skillType{}; - float m_range{}; - float m_radius{}; - uint16 m_totalTargets{}; - uint16 m_mpCost{}; // mpCost/itemId for ninjitsu tool - uint8 m_job[MAX_JOBTYPE]{}; // job - uint16 m_ValidTarget{}; // target pc/npc/both - SPELLGROUP m_spellGroup{ SPELLGROUP_NONE }; // spellgroup - SPELLFAMILY m_spellFamily{ SPELLFAMILY_NONE }; // spell family - uint16 m_zoneMisc{}; // spellcasting conditions - uint8 m_AOE{}; // aoe or single target spell - uint16 m_base{}; // spell base damage - float m_multiplier{}; // multiplier for upper tier spells - uint16 m_element{}; // element of spell - uint16 m_message{}; // message id - uint16 m_MagicBurstMessage{}; // Message used for magic bursts. - MODIFIER m_MessageModifier{}; // Message modifier, "Cover!", "Resist!" or "Immunobreak!" - int32 m_CE{}; // cumulative enmity of spell - int32 m_VE{}; // volatile enmity of spell - std::string m_name; // spell name - uint32 m_modifiedRecastTime{}; // recast time after modifications - uint8 m_requirements{}; // requirements before being able to cast spell - uint16 m_meritId{}; // associated merit (if applicable) - uint8 m_flag{}; - std::string m_contentTag{}; + SpellID m_ID; // spell id + uint32 m_primaryTargetID{}; // primary target ID + timer::duration m_castTime{}; // time to cast spell + timer::duration m_recastTime{}; // recast time + uint16 m_animation{}; // animation for spell + timer::duration m_animationTime{}; + uint8 m_skillType{}; + float m_range{}; + float m_radius{}; + uint16 m_totalTargets{}; + uint16 m_mpCost{}; // mpCost/itemId for ninjitsu tool + uint8 m_job[MAX_JOBTYPE]{}; // job + uint16 m_ValidTarget{}; // target pc/npc/both + SPELLGROUP m_spellGroup{ SPELLGROUP_NONE }; // spellgroup + SPELLFAMILY m_spellFamily{ SPELLFAMILY_NONE }; // spell family + uint16 m_zoneMisc{}; // spellcasting conditions + uint8 m_AOE{}; // aoe or single target spell + uint16 m_base{}; // spell base damage + float m_multiplier{}; // multiplier for upper tier spells + uint16 m_element{}; // element of spell + uint16 m_message{}; // message id + uint16 m_MagicBurstMessage{}; // Message used for magic bursts. + MODIFIER m_MessageModifier{}; // Message modifier, "Cover!", "Resist!" or "Immunobreak!" + int32 m_CE{}; // cumulative enmity of spell + int32 m_VE{}; // volatile enmity of spell + std::string m_name; // spell name + timer::duration m_modifiedRecastTime{}; // recast time after modifications + uint8 m_requirements{}; // requirements before being able to cast spell + uint16 m_meritId{}; // associated merit (if applicable) + uint8 m_flag{}; + std::string m_contentTag{}; }; // Namespace to work with spells diff --git a/src/map/status_effect.cpp b/src/map/status_effect.cpp index 68a2d6a0d05..b5f829bf86f 100644 --- a/src/map/status_effect.cpp +++ b/src/map/status_effect.cpp @@ -27,7 +27,7 @@ #include "status_effect_container.h" #include -CStatusEffect::CStatusEffect(EFFECT id, uint16 icon, uint16 power, uint32 tick, uint32 duration, uint32 subid, uint16 subPower, uint16 tier, uint32 flags) +CStatusEffect::CStatusEffect(EFFECT id, uint16 icon, uint16 power, timer::duration tick, timer::duration duration, uint32 subid, uint16 subPower, uint16 tier, uint32 flags) : m_StatusID(id) , m_SubID(subid) , m_Icon(icon) @@ -35,10 +35,10 @@ CStatusEffect::CStatusEffect(EFFECT id, uint16 icon, uint16 power, uint32 tick, , m_SubPower(subPower) , m_Tier(tier) , m_Flags(flags) -, m_TickTime(tick * 1000) -, m_Duration(duration * 1000) +, m_TickTime(tick) +, m_Duration(duration) { - if (m_TickTime < 3000 && m_TickTime != 0) + if (m_TickTime < 3s && m_TickTime != 0s) { ShowWarning("Status Effect tick time less than 3s is no longer supported. Effect ID: %d", id); } @@ -116,12 +116,12 @@ uint32 CStatusEffect::GetEffectFlags() const return m_Flags; } -uint32 CStatusEffect::GetTickTime() const +timer::duration CStatusEffect::GetTickTime() const { return m_TickTime; } -uint32 CStatusEffect::GetDuration() const +timer::duration CStatusEffect::GetDuration() const { return m_Duration; } @@ -131,7 +131,7 @@ int CStatusEffect::GetElapsedTickCount() const return m_tickCount; } -time_point CStatusEffect::GetStartTime() +timer::time_point CStatusEffect::GetStartTime() { return m_StartTime; } @@ -203,18 +203,18 @@ void CStatusEffect::SetTier(uint16 tier) m_Tier = tier; } -void CStatusEffect::SetDuration(uint32 Duration) +void CStatusEffect::SetDuration(timer::duration Duration) { m_Duration = Duration; } -void CStatusEffect::SetStartTime(time_point StartTime) +void CStatusEffect::SetStartTime(timer::time_point StartTime) { m_tickCount = 0; m_StartTime = StartTime; } -void CStatusEffect::SetTickTime(uint32 tick) +void CStatusEffect::SetTickTime(timer::duration tick) { m_TickTime = tick; } diff --git a/src/map/status_effect.h b/src/map/status_effect.h index 00811364307..2cec31971c9 100644 --- a/src/map/status_effect.h +++ b/src/map/status_effect.h @@ -793,11 +793,11 @@ class CStatusEffect uint16 GetEffectType() const; uint8 GetEffectSlot() const; - uint32 GetTickTime() const; - uint32 GetDuration() const; - int GetElapsedTickCount() const; - time_point GetStartTime(); - CBattleEntity* GetOwner(); + timer::duration GetTickTime() const; + timer::duration GetDuration() const; + int GetElapsedTickCount() const; + timer::time_point GetStartTime(); + CBattleEntity* GetOwner(); void SetEffectFlags(uint32 Flags); void AddEffectFlag(uint32 Flag); @@ -810,12 +810,12 @@ class CStatusEffect void SetPower(uint16 Power); void SetSubPower(uint16 subPower); void SetTier(uint16 tier); - void SetDuration(uint32 Duration); + void SetDuration(timer::duration Duration); void SetOwner(CBattleEntity* Owner); - void SetTickTime(uint32 tick); + void SetTickTime(timer::duration tick); void IncrementElapsedTickCount(); - void SetStartTime(time_point StartTime); + void SetStartTime(timer::time_point StartTime); void addMod(Mod modType, int16 amount); void setMod(Mod modType, int16 value); @@ -827,7 +827,7 @@ class CStatusEffect std::vector modList; // List of modifiers bool deleted{ false }; - CStatusEffect(EFFECT id, uint16 icon, uint16 power, uint32 tick, uint32 duration, uint32 subid = 0, uint16 subPower = 0, uint16 tier = 0, uint32 flags = 0); + CStatusEffect(EFFECT id, uint16 icon, uint16 power, timer::duration tick, timer::duration duration, uint32 subid = 0, uint16 subPower = 0, uint16 tier = 0, uint32 flags = 0); ~CStatusEffect(); @@ -846,10 +846,10 @@ class CStatusEffect uint16 m_Type{ 0 }; // Used to enforce only one uint8 m_Slot{ 0 }; // Used to determine slot order for songs/rolls - uint32 m_TickTime{ 0 }; // Effect repetition time (ms) - uint32 m_Duration{ 0 }; // Duration of effect (ms) - time_point m_StartTime; // Time to obtain effect (ms) - int m_tickCount{ 0 }; // Time of last effect execution (ms) + timer::duration m_TickTime{ 0ms }; // Effect repetition time + timer::duration m_Duration{ 0ms }; // Duration of effect + timer::time_point m_StartTime; // Time to obtain effect + int m_tickCount{ 0 }; // Elapsed ticks std::string m_Name; // Effect name for scripts }; diff --git a/src/map/status_effect_container.cpp b/src/map/status_effect_container.cpp index 420e2360b0c..5f97e2b3d1b 100644 --- a/src/map/status_effect_container.cpp +++ b/src/map/status_effect_container.cpp @@ -88,7 +88,7 @@ namespace effects uint8 Element; // minimum duration. IE: stun cannot last less than 1 second - uint32 MinDuration; + timer::duration MinDuration; // Order in which the status effect should be displayed for the player uint16 SortKey; @@ -101,7 +101,7 @@ namespace effects , BlockId((EFFECT)0) , RemoveId((EFFECT)0) , Element(0) - , MinDuration(0) + , MinDuration(0s) , SortKey(0) { } @@ -136,7 +136,7 @@ namespace effects EffectsParams[EffectID].Element = _sql->GetIntData(8); // convert from second to millisecond - EffectsParams[EffectID].MinDuration = _sql->GetIntData(9) * 1000; + EffectsParams[EffectID].MinDuration = std::chrono::seconds(_sql->GetIntData(9)); uint16 sortKey = _sql->GetIntData(10); EffectsParams[EffectID].SortKey = sortKey == 0 ? 10000 : sortKey; // default to high number to such that effects without a sort key aren't first @@ -183,7 +183,7 @@ bool statusOrdering(CStatusEffect* AStatus, CStatusEffect* BStatus) // Sort by start time if (isSortedByStartTime(AStatus->GetStatusID()) && isSortedByStartTime(BStatus->GetStatusID())) { - auto diff = std::chrono::duration_cast(AStatus->GetStartTime() - BStatus->GetStartTime()).count(); + auto diff = timer::count_milliseconds(AStatus->GetStartTime() - BStatus->GetStartTime()); if (diff != 0) { return diff > 0; @@ -235,7 +235,7 @@ uint8 CStatusEffectContainer::GetEffectsCountWithFlag(EFFECTFLAG flag) uint8 count = 0; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { count++; } @@ -509,7 +509,7 @@ bool CStatusEffectContainer::AddStatusEffect(CStatusEffect* PStatusEffect, Effec // remove effects with same type DelStatusEffectsByType(PStatusEffect->GetEffectType()); - PStatusEffect->SetStartTime(server_clock::now()); + PStatusEffect->SetStartTime(timer::now()); m_StatusEffectSet.insert(PStatusEffect); @@ -728,7 +728,7 @@ void CStatusEffectContainer::KillAllStatusEffect() for (auto effect_iter = m_StatusEffectSet.begin(); effect_iter != m_StatusEffectSet.end();) { CStatusEffect* PStatusEffect = *effect_iter; - if (PStatusEffect->GetDuration() != 0) + if (PStatusEffect->GetDuration() != 0s) { luautils::OnEffectLose(m_POwner, PStatusEffect); @@ -844,7 +844,7 @@ EFFECT CStatusEffectContainer::EraseStatusEffect() std::vector erasableList; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(EFFECTFLAG_ERASABLE) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(EFFECTFLAG_ERASABLE) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { erasableList.emplace_back(PStatusEffect); } @@ -866,7 +866,7 @@ EFFECT CStatusEffectContainer::HealingWaltz() { if ((PStatusEffect->HasEffectFlag(EFFECTFLAG_WALTZABLE) || PStatusEffect->HasEffectFlag(EFFECTFLAG_ERASABLE)) && - PStatusEffect->GetDuration() > 0 && + PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { waltzableList.emplace_back(PStatusEffect); @@ -891,7 +891,7 @@ uint8 CStatusEffectContainer::EraseAllStatusEffect() uint8 count = 0; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(EFFECTFLAG_ERASABLE) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(EFFECTFLAG_ERASABLE) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { RemoveStatusEffect(PStatusEffect); count++; @@ -911,7 +911,7 @@ EFFECT CStatusEffectContainer::DispelStatusEffect(EFFECTFLAG flag) std::vector dispelableList; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { dispelableList.emplace_back(PStatusEffect); } @@ -935,7 +935,7 @@ uint8 CStatusEffectContainer::DispelAllStatusEffect(EFFECTFLAG flag) uint8 count = 0; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { RemoveStatusEffect(PStatusEffect, EffectNotice::Silent); count++; @@ -1008,8 +1008,8 @@ bool CStatusEffectContainer::ApplyBardEffect(CStatusEffect* PStatusEffect, uint8 { oldestSong = ExistingStatusEffect; } - else if (std::chrono::milliseconds(ExistingStatusEffect->GetDuration()) + ExistingStatusEffect->GetStartTime() < - std::chrono::milliseconds(oldestSong->GetDuration()) + oldestSong->GetStartTime()) + else if (ExistingStatusEffect->GetStartTime() + ExistingStatusEffect->GetDuration() < + oldestSong->GetStartTime() + oldestSong->GetDuration()) { oldestSong = ExistingStatusEffect; } @@ -1078,9 +1078,9 @@ bool CStatusEffectContainer::ApplyCorsairEffect(CStatusEffect* PStatusEffect, ui { if (!CheckForElevenRoll()) { - uint16 duration = 300; - duration -= bustDuration; - CStatusEffect* bustEffect = new CStatusEffect(EFFECT_BUST, EFFECT_BUST, PStatusEffect->GetPower(), 0, duration, + timer::duration duration = 5min; + duration -= std::chrono::seconds(bustDuration); + CStatusEffect* bustEffect = new CStatusEffect(EFFECT_BUST, EFFECT_BUST, PStatusEffect->GetPower(), 0s, duration, PStatusEffect->GetTier(), PStatusEffect->GetStatusID()); AddStatusEffect(bustEffect, EffectNotice::Silent); DelStatusEffectSilent(EFFECT_DOUBLE_UP_CHANCE); @@ -1098,8 +1098,8 @@ bool CStatusEffectContainer::ApplyCorsairEffect(CStatusEffect* PStatusEffect, ui { oldestRoll = PEffect; } - else if (std::chrono::milliseconds(PEffect->GetDuration()) + PEffect->GetStartTime() < - std::chrono::milliseconds(oldestRoll->GetDuration()) + oldestRoll->GetStartTime()) + else if (PEffect->GetStartTime() + PEffect->GetDuration() < + oldestRoll->GetStartTime() + oldestRoll->GetDuration()) { oldestRoll = PEffect; } @@ -1341,7 +1341,7 @@ CStatusEffect* CStatusEffectContainer::StealStatusEffect(EFFECTFLAG flag, Effect std::vector dispelableList; for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0 && !PStatusEffect->deleted) + if (PStatusEffect->HasEffectFlag(flag) && PStatusEffect->GetDuration() > 0s && !PStatusEffect->deleted) { dispelableList.emplace_back(PStatusEffect); } @@ -1353,8 +1353,8 @@ CStatusEffect* CStatusEffectContainer::StealStatusEffect(EFFECTFLAG flag, Effect CStatusEffect* oldEffect = dispelableList.at(rndIdx); // make a copy - CStatusEffect* EffectCopy = new CStatusEffect(oldEffect->GetStatusID(), oldEffect->GetIcon(), oldEffect->GetPower(), oldEffect->GetTickTime() / 1000, - oldEffect->GetDuration() / 1000, oldEffect->GetSubID(), oldEffect->GetSubPower(), oldEffect->GetTier(), + CStatusEffect* EffectCopy = new CStatusEffect(oldEffect->GetStatusID(), oldEffect->GetIcon(), oldEffect->GetPower(), oldEffect->GetTickTime(), + oldEffect->GetDuration(), oldEffect->GetSubID(), oldEffect->GetSubPower(), oldEffect->GetTier(), oldEffect->GetEffectFlags()); RemoveStatusEffect(oldEffect, notice); @@ -1633,24 +1633,24 @@ void CStatusEffectContainer::LoadStatusEffects() { while (rset->next()) { - auto flags = rset->get("flags"); - auto duration = rset->get("duration"); - auto effectID = static_cast(rset->get("effectid")); + auto flags = rset->get("flags"); + timer::duration duration = std::chrono::seconds(rset->get("duration")); + auto effectID = static_cast(rset->get("effectid")); if (flags & EFFECTFLAG_OFFLINE_TICK) { - auto timestamp = rset->get("timestamp"); - if (server_clock::now() < time_point() + std::chrono::seconds(timestamp) + std::chrono::seconds(duration)) + auto currentTime = timer::now(); + auto startTime = timer::from_utc(earth_time::time_point(std::chrono::seconds(rset->get("timestamp")))); + auto endTime = startTime + duration; + if (currentTime < endTime) { - duration = (uint32)std::chrono::duration_cast(time_point() + std::chrono::seconds(timestamp) + - std::chrono::seconds(duration) - server_clock::now()) - .count(); + duration = endTime - currentTime; } else if (effectID == EFFECT::EFFECT_VISITANT) { // Visitant effect expired while offline, but there's other logic to handle. // Set duration to 1 so that it expires after zoning in, and the player is ejected. - duration = 1; + duration = 1s; } else { @@ -1662,7 +1662,7 @@ void CStatusEffectContainer::LoadStatusEffects() new CStatusEffect(effectID, rset->get("icon"), rset->get("power"), - rset->get("tick"), + std::chrono::seconds(rset->get("tick")), duration, rset->get("subid"), rset->get("subpower"), @@ -1722,9 +1722,9 @@ void CStatusEffectContainer::SaveStatusEffects(bool logout) continue; } - auto realduration = std::chrono::milliseconds(PStatusEffect->GetDuration()) + PStatusEffect->GetStartTime() - server_clock::now(); + auto realduration = PStatusEffect->GetStartTime() + PStatusEffect->GetDuration() - timer::now(); - if (realduration > 0s || PStatusEffect->GetDuration() == 0) + if (realduration > 0s || PStatusEffect->GetDuration() == 0s) { const char* Query = "INSERT INTO char_effects (charid, effectid, icon, power, tick, duration, subid, subpower, tier, flags, timestamp) " "VALUES(%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)"; @@ -1743,22 +1743,20 @@ void CStatusEffectContainer::SaveStatusEffects(bool logout) PStatusEffect->SetPower(m_POwner->getMod(Mod::STONESKIN)); } - uint32 tick = PStatusEffect->GetTickTime() == 0 ? 0 : PStatusEffect->GetTickTime() / 1000; + uint32 tick = static_cast(timer::count_seconds(PStatusEffect->GetTickTime())); uint32 duration = 0; - if (PStatusEffect->GetDuration() > 0) + if (PStatusEffect->GetDuration() > 0s) { if (PStatusEffect->HasEffectFlag(EFFECTFLAG_OFFLINE_TICK)) { - duration = PStatusEffect->GetDuration() / 1000; + duration = static_cast(timer::count_seconds(PStatusEffect->GetDuration())); } else { - auto seconds = (uint32)std::chrono::duration_cast(realduration).count(); - - if (seconds > 0) + if (realduration > 0s) { - duration = seconds; + duration = static_cast(timer::count_seconds(realduration)); } else { @@ -1766,9 +1764,10 @@ void CStatusEffectContainer::SaveStatusEffects(bool logout) } } } + auto timestamp = earth_time::timestamp(timer::to_utc(PStatusEffect->GetStartTime())); _sql->Query(Query, m_POwner->id, PStatusEffect->GetStatusID(), PStatusEffect->GetIcon(), PStatusEffect->GetPower(), tick, duration, PStatusEffect->GetSubID(), PStatusEffect->GetSubPower(), PStatusEffect->GetTier(), PStatusEffect->GetEffectFlags(), - std::chrono::duration_cast(PStatusEffect->GetStartTime().time_since_epoch()).count()); + timestamp); } } DeleteStatusEffects(); @@ -1780,7 +1779,7 @@ void CStatusEffectContainer::SaveStatusEffects(bool logout) * * ************************************************************************/ -void CStatusEffectContainer::CheckEffectsExpiry(time_point tick) +void CStatusEffectContainer::CheckEffectsExpiry(timer::time_point tick) { if (m_POwner == nullptr) { @@ -1792,7 +1791,7 @@ void CStatusEffectContainer::CheckEffectsExpiry(time_point tick) for (CStatusEffect* PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->GetDuration() != 0 && std::chrono::milliseconds(PStatusEffect->GetDuration()) + PStatusEffect->GetStartTime() <= tick) + if (PStatusEffect->GetDuration() != 0s && PStatusEffect->GetStartTime() + PStatusEffect->GetDuration() <= tick) { RemoveStatusEffect(PStatusEffect); } @@ -1832,7 +1831,7 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) if (PEffect && (PEffect->GetEffectFlags() & EFFECTFLAG_ALWAYS_EXPIRING) != 0) { - PEffect->SetStartTime(server_clock::now()); + PEffect->SetStartTime(timer::now()); // Effect updated, probably from Ecliptic Attrition // Update status effect with new potency. @@ -1850,8 +1849,8 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) PEffect = new CStatusEffect(static_cast(PStatusEffect->GetSubID()), // Effect ID PStatusEffect->GetSubID(), // Effect Icon (Associated with ID) PStatusEffect->GetSubPower(), // Power - 3, // Tick - 4); // Duration + 3s, // Tick + 4s); // Duration PEffect->AddEffectFlag(EFFECTFLAG_NO_LOSS_MESSAGE); PEffect->AddEffectFlag(EFFECTFLAG_ALWAYS_EXPIRING); PMember->StatusEffectContainer->AddStatusEffect(PEffect, EffectNotice::Silent); @@ -1874,7 +1873,7 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) if (PEffect && (PEffect->GetEffectFlags() & EFFECTFLAG_ALWAYS_EXPIRING) != 0) { - PEffect->SetStartTime(server_clock::now()); + PEffect->SetStartTime(timer::now()); // Effect updated, probably from Ecliptic Attrition // Update status effect with new potency. @@ -1892,8 +1891,8 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) PEffect = new CStatusEffect(static_cast(PStatusEffect->GetSubID()), // Effect ID PStatusEffect->GetSubID(), // Effect Icon (Associated with ID) PStatusEffect->GetSubPower(), // Power - 3, // Tick - 4); // Duration + 3s, // Tick + 4s); // Duration PEffect->AddEffectFlag(EFFECTFLAG_NO_LOSS_MESSAGE); PEffect->AddEffectFlag(EFFECTFLAG_ALWAYS_EXPIRING); PTarget->StatusEffectContainer->AddStatusEffect(PEffect, EffectNotice::Silent); @@ -1919,7 +1918,7 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) if (PEffect && (PEffect->GetEffectFlags() & EFFECTFLAG_ALWAYS_EXPIRING) != 0) { - PEffect->SetStartTime(server_clock::now()); + PEffect->SetStartTime(timer::now()); // Effect updated, probably from Ecliptic Attrition // Update status effect with new potency. @@ -1937,8 +1936,8 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) PEffect = new CStatusEffect(static_cast(PStatusEffect->GetSubID()), // Effect ID PStatusEffect->GetSubID(), // Effect Icon (Associated with ID) PStatusEffect->GetSubPower(), // Power - 3, // Tick - 4); // Duration + 3s, // Tick + 4s); // Duration PEffect->AddEffectFlag(EFFECTFLAG_NO_LOSS_MESSAGE); PEffect->AddEffectFlag(EFFECTFLAG_ALWAYS_EXPIRING); PMember->StatusEffectContainer->AddStatusEffect(PEffect, EffectNotice::Silent); @@ -1964,7 +1963,7 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) if (PEffect && (PEffect->GetEffectFlags() & EFFECTFLAG_ALWAYS_EXPIRING) != 0) { - PEffect->SetStartTime(server_clock::now()); + PEffect->SetStartTime(timer::now()); // Effect updated, probably from Ecliptic Attrition // Update status effect with new potency. @@ -1982,8 +1981,8 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) PEffect = new CStatusEffect(static_cast(PStatusEffect->GetSubID()), // Effect ID PStatusEffect->GetSubID(), // Effect Icon (Associated with ID) PStatusEffect->GetSubPower(), // Power - 3, // Tick - 4); // Duration + 3s, // Tick + 4s); // Duration PEffect->AddEffectFlag(EFFECTFLAG_NO_LOSS_MESSAGE); PEffect->AddEffectFlag(EFFECTFLAG_ALWAYS_EXPIRING); PTarget->StatusEffectContainer->AddStatusEffect(PEffect, EffectNotice::Silent); @@ -2000,7 +1999,7 @@ void CStatusEffectContainer::HandleAura(CStatusEffect* PStatusEffect) * * ************************************************************************/ -void CStatusEffectContainer::TickEffects(time_point tick) +void CStatusEffectContainer::TickEffects(timer::time_point tick) { TracyZoneScoped; @@ -2014,9 +2013,8 @@ void CStatusEffectContainer::TickEffects(time_point tick) { for (const auto& PStatusEffect : m_StatusEffectSet) { - if (PStatusEffect->GetTickTime() != 0 && - PStatusEffect->GetElapsedTickCount() <= - std::chrono::duration_cast(tick - PStatusEffect->GetStartTime()).count() / PStatusEffect->GetTickTime()) + if (PStatusEffect->GetTickTime() != 0s && + PStatusEffect->GetElapsedTickCount() <= (tick - PStatusEffect->GetStartTime()) / PStatusEffect->GetTickTime()) { if (PStatusEffect->HasEffectFlag(EFFECTFLAG_AURA)) { @@ -2037,7 +2035,7 @@ void CStatusEffectContainer::TickEffects(time_point tick) * * ************************************************************************/ -void CStatusEffectContainer::TickRegen(time_point tick) +void CStatusEffectContainer::TickRegen(timer::time_point tick) { TracyZoneScoped; diff --git a/src/map/status_effect_container.h b/src/map/status_effect_container.h index eab6d09bb27..351d37181d8 100644 --- a/src/map/status_effect_container.h +++ b/src/map/status_effect_container.h @@ -88,9 +88,9 @@ class CStatusEffectContainer void RemoveAllStatusEffectsInIDRange(EFFECT start, EFFECT end); void UpdateStatusIcons(); // We recall the effects of the effects - void CheckEffectsExpiry(time_point tick); - void TickEffects(time_point tick); - void TickRegen(time_point tick); + void CheckEffectsExpiry(timer::time_point tick); + void TickEffects(timer::time_point tick); + void TickRegen(timer::time_point tick); void LoadStatusEffects(); // We load the character effects void SaveStatusEffects(bool logout = false); // We keep the character effects diff --git a/src/map/time_server.cpp b/src/map/time_server.cpp index 147e500ed72..fb7cb5caaa0 100644 --- a/src/map/time_server.cpp +++ b/src/map/time_server.cpp @@ -24,11 +24,11 @@ #include "common/logging.h" #include "common/vana_time.h" -#include "common/vana_time.h" #include "daily_system.h" #include "entities/charentity.h" #include "latent_effect_container.h" #include "lua/luautils.h" +#include "map_constants.h" #include "roe.h" #include "timetriggers.h" #include "transport.h" @@ -37,104 +37,97 @@ #include "utils/moduleutils.h" #include "utils/zoneutils.h" -int32 time_server(time_point tick, CTaskManager::CTask* PTask) +int32 time_server(timer::time_point tick, CTaskManager::CTask* PTask) { TracyZoneScoped; - TIMETYPE VanadielTOTD = CVanaTime::getInstance()->SyncTime(); - // uint8 WeekDay = (uint8)CVanaTime::getInstance()->getWeekday(); - - // Weekly update for conquest (sunday at midnight) - static time_point lastConquestTally = tick - 1h; - static time_point lastConquestUpdate = tick - 1h; - static time_point lastZnmPriceDecay = tick - 1h; + // Track elapsed ticks. + static auto tickNum = 0; + ++tickNum; - if (CVanaTime::getInstance()->getJstWeekDay() == 1 && CVanaTime::getInstance()->getJstHour() == 0 && CVanaTime::getInstance()->getJstMinute() == 0) - { - if (tick > (lastConquestTally + 1h)) - { - roeutils::CycleWeeklyRecords(); - roeutils::CycleUnityRankings(); - lastConquestTally = tick; - } - } - // Hourly conquest update - else if (CVanaTime::getInstance()->getJstMinute() == 0) - { - if (tick > (lastConquestUpdate + 1h)) - { - roeutils::UpdateUnityRankings(); - lastConquestUpdate = tick; - } + // Earth-based ticks. + // Uses the JST equivalent of the current timer tick. (steady_clock -> system_clock) - // ZNM Pop-Item Prices Decay every 2 hours - if (CVanaTime::getInstance()->getJstHour() % 2 == 0) - { - if (tick > (lastZnmPriceDecay + 1h)) - { - luautils::ZNMPopPriceDecay(); - lastZnmPriceDecay = tick; - } - } - } - - // Vanadiel Hour - static time_point lastVHourlyUpdate = tick - 4800ms; - if (CVanaTime::getInstance()->getMinute() == 0) - { - if (tick > (lastVHourlyUpdate + 4800ms)) - { - // clang-format off - zoneutils::ForEachZone([](CZone* PZone) - { - luautils::OnGameHour(PZone); - PZone->ForEachChar([](CCharEntity* PChar) - { - PChar->PLatentEffectContainer->CheckLatentsHours(); - PChar->PLatentEffectContainer->CheckLatentsMoonPhase(); - }); - }); - // clang-format on + // Earth time points + const auto jstTime = earth_time::time_point(timer::to_utc(tick)); + const auto jstHour = earth_time::jst::get_hour(jstTime); + const auto jstWeekday = earth_time::jst::get_weekday(jstTime); - lastVHourlyUpdate = tick; - } - } + // Static variable for the next tick + static auto nextHourlyTick = std::chrono::ceil(jstTime); - // JST Midnight - static time_point lastTickedJstMidnight = tick - 1h; - if (CVanaTime::getInstance()->getJstHour() == 0 && CVanaTime::getInstance()->getJstMinute() == 0) + // Hourly ticks + if (jstTime >= nextHourlyTick) { - if (tick > (lastTickedJstMidnight + 1h)) + if (jstHour == 0) { - if (settings::get("main.ENABLE_ROE")) + // Daily tick (midnight JST) + ShowDebugFmt("Daily tick... (current tick: {})", tickNum); + if (jstWeekday == 1) { - roeutils::CycleDailyRecords(); + // Weekly tick (Monday JST) + ShowDebugFmt("Weekly tick... (current tick: {})", tickNum); + roeutils::CycleWeeklyRecords(); + roeutils::CycleUnityRankings(); } - + roeutils::CycleDailyRecords(); guildutils::UpdateGuildPointsPattern(); luautils::OnJSTMidnight(); luautils::UpdateSanrakusMobs(); - lastTickedJstMidnight = tick; } - } + // 1-hour tick + ShowDebugFmt("1-hour tick... (current tick: {})", tickNum); + roeutils::UpdateUnityRankings(); - // 4-hour RoE Timed blocks - static time_point lastTickedRoeBlock = tick - 1h; - if (CVanaTime::getInstance()->getJstHour() % 4 == 0 && CVanaTime::getInstance()->getJstMinute() == 0) - { - if (tick > (lastTickedRoeBlock + 1h)) + if (jstHour % 2 == 0) { - roeutils::CycleTimedRecords(); - lastTickedRoeBlock = tick; + // 2-hour tick + ShowDebugFmt("2-hour tick... (current tick: {})", tickNum); + luautils::ZNMPopPriceDecay(); + if (jstHour % 4 == 0) + { + // 4-hour tick + ShowDebugFmt("4-hour tick... (current tick: {})", tickNum); + roeutils::CycleTimedRecords(); + } } + + nextHourlyTick = std::chrono::ceil(jstTime); } - // Vanadiel Day - static time_point lastVDailyUpdate = tick - 4800ms; - if (CVanaTime::getInstance()->getHour() == 0 && CVanaTime::getInstance()->getMinute() == 0) + // Vana'diel-based ticks. + // Uses the Vana'diel time equivalent of the current JST time. (steady_clock -> system_clock -> vanadiel_clock) + // Note: Vana'diel minute is equal to the tick interval (2400ms). It is possible to miss a minute if there is + // variance in the tick time. + + // Vana'diel time points + const auto vanaTime = vanadiel_time::from_earth_time(jstTime); + const auto vanaTotd = vanadiel_time::get_totd(vanaTime); + const auto vanaHour = vanadiel_time::get_hour(vanaTime); + + // Static variables for the next tick + static auto nextVHourlyUpdate = std::chrono::ceil(vanaTime); + static auto prevTotd = vanaTotd; + + if (vanaTime >= nextVHourlyUpdate) { - TracyZoneScoped; - if (tick > (lastVDailyUpdate + 4800ms)) + // Vana'diel Hour + // clang-format off + zoneutils::ForEachZone([](CZone* PZone) { + luautils::OnGameHour(PZone); + PZone->ForEachChar([](CCharEntity* PChar) + { + PChar->PLatentEffectContainer->CheckLatentsHours(); + PChar->PLatentEffectContainer->CheckLatentsMoonPhase(); + }); + }); + // clang-format on + + if (vanaHour == 0) + { + // Vana'diel Day + TracyZoneScoped; + ShowDebugFmt("Vana'diel day tick... (current tick: {})", tickNum); // clang-format off zoneutils::ForEachZone([](CZone* PZone) { @@ -145,43 +138,39 @@ int32 time_server(time_point tick, CTaskManager::CTask* PTask) }); }); // clang-format on - guildutils::UpdateGuildsStock(); zoneutils::SavePlayTime(); - - lastVDailyUpdate = tick; } - } - - // Some notable time-event has occurred. -- CVanaTime::SyncTime() has hit a time of day where latents trigger - if (VanadielTOTD != TIME_NONE) - { - TracyZoneScoped; - zoneutils::TOTDChange(VanadielTOTD); - // clang-format off - zoneutils::ForEachZone([](CZone* PZone) + if (vanaTotd != prevTotd) { - PZone->ForEachChar([](CCharEntity* PChar) + // MIDNIGHT -> NEWDAY -> DAWN -> DAY -> DUSK -> EVENING -> NIGHT + TracyZoneScoped; + zoneutils::TOTDChange(vanaTotd); + fishingutils::RestockFishingAreas(); + + // clang-format off + zoneutils::ForEachZone([](CZone* PZone) { - PChar->PLatentEffectContainer->CheckLatentsDay(); - PChar->PLatentEffectContainer->CheckLatentsJobLevel(); // Eerie CLoak +1 latent is nighttime + level multiple of 13 + PZone->ForEachChar([](CCharEntity* PChar) + { + PChar->PLatentEffectContainer->CheckLatentsDay(); + PChar->PLatentEffectContainer->CheckLatentsJobLevel(); // Eerie CLoak +1 latent is nighttime + level multiple of 13 + }); }); - }); - // clang-format on + // clang-format on + + prevTotd = vanaTotd; + } - fishingutils::RestockFishingAreas(); + nextVHourlyUpdate = std::chrono::ceil(vanaTime); } CTriggerHandler::getInstance()->triggerTimer(); CTransportHandler::getInstance()->TransportTimer(); - instanceutils::CheckInstance(); - luautils::OnTimeServerTick(); - luautils::TryReloadFilewatchList(); - moduleutils::OnTimeServerTick(); TracyFrameMark; diff --git a/src/map/time_server.h b/src/map/time_server.h index 6f895d5caed..03b4a0fab2a 100644 --- a/src/map/time_server.h +++ b/src/map/time_server.h @@ -24,7 +24,8 @@ #include "common/cbasetypes.h" #include "common/task_manager.h" +#include "common/timer.h" -int32 time_server(time_point tick, CTaskManager::CTask*); +int32 time_server(timer::time_point tick, CTaskManager::CTask*); #endif diff --git a/src/map/timetriggers.cpp b/src/map/timetriggers.cpp index e0593f60034..c42c306785b 100644 --- a/src/map/timetriggers.cpp +++ b/src/map/timetriggers.cpp @@ -27,20 +27,23 @@ void CTriggerHandler::insertTrigger(Trigger_t trigger) { - trigger.lastTrigger = (CVanaTime::getInstance()->getDate() - trigger.minuteOffset) / trigger.period; + vanadiel_time::duration alignedTime = vanadiel_time::now().time_since_epoch() - trigger.minuteOffset; + trigger.lastTrigger = alignedTime / trigger.period; triggerList.emplace_back(trigger); } void CTriggerHandler::triggerTimer() { - uint32 vanaTime = CVanaTime::getInstance()->getDate(); - uint32 timeCount = 0; - Trigger_t* trigger = nullptr; + Trigger_t* trigger = nullptr; + vanadiel_time::duration vanaTime = vanadiel_time::now().time_since_epoch(); + vanadiel_time::duration alignedTime; + uint32 timeCount; for (auto& i : triggerList) { - trigger = &i; - timeCount = (vanaTime - trigger->minuteOffset) / trigger->period; + trigger = &i; + alignedTime = vanaTime - trigger->minuteOffset; + timeCount = alignedTime / trigger->period; if (timeCount > trigger->lastTrigger) { diff --git a/src/map/timetriggers.h b/src/map/timetriggers.h index cf7c3e06e17..4a8bbe223ea 100644 --- a/src/map/timetriggers.h +++ b/src/map/timetriggers.h @@ -24,6 +24,7 @@ #include "common/cbasetypes.h" #include "common/singleton.h" +#include "common/vana_time.h" #include "entities/npcentity.h" #include @@ -33,8 +34,8 @@ struct Trigger_t CNpcEntity* npc; // NPC entity that the trigger belongs to - uint16 period; // The time in vanadiel minutes between two firings of the trigger - uint16 minuteOffset; // The time in vanadiel minutes after SE epoch which the period syncs to + vanadiel_time::duration period; // The vanadiel time between two firings of the trigger + vanadiel_time::duration minuteOffset; // The vanadiel time after SE epoch which the period syncs to uint32 lastTrigger; // Used to store the last firing of the trigger }; diff --git a/src/map/transport.cpp b/src/map/transport.cpp index 987de02ed4d..1dd97c94e10 100644 --- a/src/map/transport.cpp +++ b/src/map/transport.cpp @@ -51,10 +51,10 @@ void Transport_Ship::setVisible(bool visible) const } } -void Transport_Ship::animateSetup(uint8 animationID, uint32 horizonTime) const +void Transport_Ship::animateSetup(uint8 animationID, vanadiel_time::time_point horizonTime) const { this->npc->animation = animationID; - this->npc->SetLocalVar("TransportTimestamp", horizonTime); + this->npc->SetLocalVar("TransportTimestamp", earth_time::vanadiel_timestamp(vanadiel_time::to_earth_time(horizonTime))); } void Transport_Ship::spawn() const @@ -152,11 +152,11 @@ void CTransportHandler::InitializeTransport(IPP mapIPP) zoneTown.ship.animationArrive = (uint8)_sql->GetIntData(9); zoneTown.ship.animationDepart = (uint8)_sql->GetIntData(10); - zoneTown.ship.timeOffset = (uint16)_sql->GetIntData(11); - zoneTown.ship.timeInterval = (uint16)_sql->GetIntData(12); - zoneTown.ship.timeArriveDock = (uint16)_sql->GetIntData(14); - zoneTown.ship.timeDepartDock = zoneTown.ship.timeArriveDock + (uint16)_sql->GetIntData(13); - zoneTown.ship.timeVoyageStart = zoneTown.ship.timeDepartDock + (uint16)_sql->GetIntData(15) - 1; + zoneTown.ship.timeOffset = xi::vanadiel_clock::minutes(_sql->GetIntData(11)); + zoneTown.ship.timeInterval = xi::vanadiel_clock::minutes(_sql->GetIntData(12)); + zoneTown.ship.timeArriveDock = xi::vanadiel_clock::minutes(_sql->GetIntData(14)); + zoneTown.ship.timeDepartDock = zoneTown.ship.timeArriveDock + xi::vanadiel_clock::minutes(_sql->GetIntData(13)); + zoneTown.ship.timeVoyageStart = zoneTown.ship.timeDepartDock + xi::vanadiel_clock::minutes(_sql->GetIntData(15) - 1); zoneTown.ship.state = STATE_TRANSPORT_INIT; zoneTown.ship.setVisible(false); @@ -167,7 +167,7 @@ void CTransportHandler::InitializeTransport(IPP mapIPP) ShowError("Transport <%u>: door not found", (uint8)_sql->GetIntData(0)); continue; } - if (zoneTown.ship.timeArriveDock < 10) + if (zoneTown.ship.timeArriveDock < xi::vanadiel_clock::minutes(10)) { ShowError("Transport <%u>: time_anim_arrive must be > 10", (uint8)_sql->GetIntData(0)); continue; @@ -199,12 +199,12 @@ void CTransportHandler::InitializeTransport(IPP mapIPP) if (voyageZone.voyageZone != nullptr && voyageZone.voyageZone->GetID() > 0) { - voyageZone.timeOffset = (uint16)_sql->GetIntData(1); - voyageZone.timeInterval = (uint16)_sql->GetIntData(2); + voyageZone.timeOffset = xi::vanadiel_clock::minutes(_sql->GetIntData(1)); + voyageZone.timeInterval = xi::vanadiel_clock::minutes(_sql->GetIntData(2)); - voyageZone.timeArriveDock = (uint16)_sql->GetIntData(4); - voyageZone.timeDepartDock = voyageZone.timeArriveDock + (uint16)_sql->GetIntData(3); - voyageZone.timeVoyageStart = voyageZone.timeDepartDock + (uint16)_sql->GetIntData(5); + voyageZone.timeArriveDock = xi::vanadiel_clock::minutes(_sql->GetIntData(4)); + voyageZone.timeDepartDock = voyageZone.timeArriveDock + xi::vanadiel_clock::minutes(_sql->GetIntData(3)); + voyageZone.timeVoyageStart = voyageZone.timeDepartDock + xi::vanadiel_clock::minutes(_sql->GetIntData(5)); voyageZone.state = STATE_TRANSPORTZONE_INIT; @@ -226,22 +226,25 @@ void CTransportHandler::InitializeTransport(IPP mapIPP) void CTransportHandler::TransportTimer() { - uint32 vanaTime = CVanaTime::getInstance()->getDate(); - uint16 shipTimerOffset = 0; + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + vanadiel_time::duration vanaTimeDuration = vanaTime.time_since_epoch(); + vanadiel_time::duration alignedTime; + vanadiel_time::duration shipTimerOffset; // Loop through town zones and update transportion accordingly for (auto& i : townZoneList) { TransportZone_Town* townZone = &i; - shipTimerOffset = ((vanaTime - townZone->ship.timeOffset) % townZone->ship.timeInterval); + alignedTime = vanaTimeDuration - townZone->ship.timeOffset; + shipTimerOffset = alignedTime % townZone->ship.timeInterval; if (townZone->ship.state == STATE_TRANSPORT_AWAY) { if (shipTimerOffset < townZone->ship.timeArriveDock) { townZone->ship.state = STATE_TRANSPORT_ARRIVING; - townZone->ship.animateSetup(townZone->ship.animationArrive, CVanaTime::getInstance()->getVanaTime()); + townZone->ship.animateSetup(townZone->ship.animationArrive, vanaTime); townZone->ship.spawn(); townZone->updateShip(); @@ -262,7 +265,7 @@ void CTransportHandler::TransportTimer() if (shipTimerOffset >= townZone->ship.timeDepartDock) { townZone->ship.state = STATE_TRANSPORT_DEPARTING; - townZone->ship.animateSetup(townZone->ship.animationDepart, CVanaTime::getInstance()->getVanaTime()); + townZone->ship.animateSetup(townZone->ship.animationDepart, vanaTime); townZone->closeDoor(true); townZone->depart(); @@ -285,24 +288,24 @@ void CTransportHandler::TransportTimer() } else if (shipTimerOffset >= townZone->ship.timeDepartDock) { - uint32 departTime = shipTimerOffset - townZone->ship.timeDepartDock; - townZone->ship.state = STATE_TRANSPORT_DEPARTING; + vanadiel_time::duration departTime = shipTimerOffset - townZone->ship.timeDepartDock; + townZone->ship.state = STATE_TRANSPORT_DEPARTING; townZone->ship.spawn(); - townZone->ship.animateSetup(townZone->ship.animationDepart, (uint32)(CVanaTime::getInstance()->getVanaTime() - departTime * 2.4)); + townZone->ship.animateSetup(townZone->ship.animationDepart, vanaTime - departTime); } else if (shipTimerOffset >= townZone->ship.timeArriveDock) { townZone->ship.state = STATE_TRANSPORT_DOCKED; townZone->openDoor(false); townZone->ship.spawn(); - townZone->ship.animateSetup(townZone->ship.animationArrive, (uint32)(CVanaTime::getInstance()->getVanaTime() - shipTimerOffset * 2.4)); + townZone->ship.animateSetup(townZone->ship.animationArrive, vanaTime - shipTimerOffset); } else { townZone->ship.state = STATE_TRANSPORT_ARRIVING; townZone->ship.spawn(); - townZone->ship.animateSetup(townZone->ship.animationArrive, (uint32)(CVanaTime::getInstance()->getVanaTime() - shipTimerOffset * 2.4)); + townZone->ship.animateSetup(townZone->ship.animationArrive, vanaTime - shipTimerOffset); } } else @@ -316,12 +319,13 @@ void CTransportHandler::TransportTimer() { TransportZone_Voyage* zoneIterator = &i; - shipTimerOffset = ((vanaTime - zoneIterator->timeOffset) % zoneIterator->timeInterval); + alignedTime = vanaTimeDuration - zoneIterator->timeOffset; + shipTimerOffset = alignedTime % zoneIterator->timeInterval; if (zoneIterator->state == STATE_TRANSPORTZONE_VOYAGE) { // Zone them out 10 Van minutes before the boat reaches the dock - if (shipTimerOffset < zoneIterator->timeVoyageStart && shipTimerOffset > zoneIterator->timeArriveDock - 10) + if (shipTimerOffset < zoneIterator->timeVoyageStart && shipTimerOffset > zoneIterator->timeArriveDock - xi::vanadiel_clock::minutes(10)) { zoneIterator->state = STATE_TRANSPORTZONE_EVICT; } @@ -439,8 +443,9 @@ void CTransportHandler::insertElevator(Elevator_t elevator) } // Have permanent elevators wait until their next cycle to begin moving - uint32 VanaTime = CVanaTime::getInstance()->getDate(); - elevator.lastTrigger = VanaTime - (VanaTime % elevator.interval) + elevator.interval; + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + vanadiel_time::duration vanaTimeDuration = vanaTime.time_since_epoch(); + elevator.lastTrigger = vanaTime - (vanaTimeDuration % elevator.interval) + elevator.interval; // Initialize the elevator into the correct state based on // its animation value in the database. @@ -500,7 +505,7 @@ void CTransportHandler::startElevator(int32 elevatorID) ************************************************************************/ void CTransportHandler::startElevator(Elevator_t* elevator) { - uint32 VanaTime = CVanaTime::getInstance()->getDate(); + vanadiel_time::time_point vanaTime = vanadiel_time::now(); // Take care of animation and state changes if (elevator->state == STATE_ELEVATOR_TOP) @@ -523,15 +528,15 @@ void CTransportHandler::startElevator(Elevator_t* elevator) // Update elevator params if (!elevator->isPermanent) { - elevator->lastTrigger = VanaTime; + elevator->lastTrigger = vanaTime; elevator->activated = true; } else { - elevator->lastTrigger = VanaTime - VanaTime % elevator->interval; // Keep the elevators synced to Vanadiel time + elevator->lastTrigger = vanaTime - (vanaTime.time_since_epoch() % elevator->interval); // Keep the elevators synced to Vanadiel time } - elevator->Elevator->SetLocalVar("TransportTimestamp", CVanaTime::getInstance()->getVanaTime()); + elevator->Elevator->SetLocalVar("TransportTimestamp", earth_time::vanadiel_timestamp(vanadiel_time::to_earth_time(vanaTime))); zoneutils::GetZone(elevator->zoneID)->UpdateEntityPacket(elevator->Elevator, ENTITY_UPDATE, UPDATE_COMBAT, true); } diff --git a/src/map/transport.h b/src/map/transport.h index d4bdeb94176..68ae0b12a57 100644 --- a/src/map/transport.h +++ b/src/map/transport.h @@ -25,6 +25,7 @@ #include "common/cbasetypes.h" #include "common/ipp.h" #include "common/singleton.h" +#include "common/vana_time.h" #include "entities/npcentity.h" @@ -58,11 +59,11 @@ enum ELEVATORSTATE struct Transport_Time { - uint16 timeOffset; - uint16 timeInterval; - uint16 timeArriveDock; - uint16 timeDepartDock; - uint16 timeVoyageStart; + vanadiel_time::duration timeOffset; + vanadiel_time::duration timeInterval; + vanadiel_time::duration timeArriveDock; + vanadiel_time::duration timeDepartDock; + vanadiel_time::duration timeVoyageStart; }; struct Transport_Ship : Transport_Time @@ -75,7 +76,7 @@ struct Transport_Ship : Transport_Time location_t dock; void setVisible(bool) const; - void animateSetup(uint8, uint32) const; + void animateSetup(uint8, vanadiel_time::time_point) const; void spawn() const; }; @@ -102,11 +103,11 @@ struct Elevator_t uint8 id; uint8 state; - uint16 zoneID; - uint32 lastTrigger; + uint16 zoneID; + vanadiel_time::time_point lastTrigger; - uint16 interval; - uint16 movetime; + vanadiel_time::duration interval; + vanadiel_time::duration movetime; CNpcEntity* Elevator; CNpcEntity* LowerDoor; diff --git a/src/map/treasure_pool.cpp b/src/map/treasure_pool.cpp index ab6e2e504ed..102a5ad7f85 100644 --- a/src/map/treasure_pool.cpp +++ b/src/map/treasure_pool.cpp @@ -32,8 +32,8 @@ #include "utils/charutils.h" #include "utils/itemutils.h" -static constexpr duration treasure_checktime = 3s; -static constexpr duration treasure_livetime = 5min; +static constexpr timer::duration treasure_checktime = 3s; +static constexpr timer::duration treasure_livetime = 5min; CTreasurePool::CTreasurePool(const TreasurePoolType PoolType) : m_count(0) @@ -165,10 +165,10 @@ void CTreasurePool::delMember(CCharEntity* PChar) uint8 CTreasurePool::addItem(uint16 ItemID, CBaseEntity* PEntity) { - uint8 SlotID = 0; - uint8 FreeSlotID = -1; - time_point oldest = time_point::max(); - CItem* PNewItem = itemutils::GetItemPointer(ItemID); + uint8 SlotID = 0; + uint8 FreeSlotID = -1; + timer::time_point oldest = timer::time_point::max(); + CItem* PNewItem = itemutils::GetItemPointer(ItemID); if (!PNewItem) { @@ -254,13 +254,13 @@ uint8 CTreasurePool::addItem(uint16 ItemID, CBaseEntity* PEntity) if (SlotID == 10) { - m_PoolItems[FreeSlotID].TimeStamp = get_server_start_time(); - checkTreasureItem(server_clock::now(), FreeSlotID); + m_PoolItems[FreeSlotID].TimeStamp = timer::start_time; + checkTreasureItem(timer::now(), FreeSlotID); } m_count++; m_PoolItems[FreeSlotID].ID = ItemID; - m_PoolItems[FreeSlotID].TimeStamp = server_clock::now() - treasure_checktime; + m_PoolItems[FreeSlotID].TimeStamp = timer::now() - treasure_checktime; for (const auto& member : m_Members) { @@ -269,7 +269,7 @@ uint8 CTreasurePool::addItem(uint16 ItemID, CBaseEntity* PEntity) if (memberCount() == 1) { - checkTreasureItem(server_clock::now(), FreeSlotID); + checkTreasureItem(timer::now(), FreeSlotID); } return m_count; @@ -296,7 +296,7 @@ void CTreasurePool::flush() { if (m_count != 0) { - const auto tick = server_clock::now() + treasure_checktime + std::chrono::seconds(1); + const auto tick = timer::now() + treasure_checktime + 1s; for (uint8 i = 0; i < TREASUREPOOL_SIZE; ++i) { @@ -472,7 +472,7 @@ bool CTreasurePool::hasPassedItem(CCharEntity* PChar, uint8 SlotID) return false; } -void CTreasurePool::checkItems(time_point tick) +void CTreasurePool::checkItems(timer::time_point tick) { if (m_count != 0) { @@ -487,7 +487,7 @@ void CTreasurePool::checkItems(time_point tick) } } -void CTreasurePool::checkTreasureItem(time_point tick, uint8 SlotID) +void CTreasurePool::checkTreasureItem(timer::time_point tick, uint8 SlotID) { if (m_PoolItems[SlotID].ID == 0) { @@ -576,7 +576,7 @@ void CTreasurePool::treasureWon(CCharEntity* winner, uint8 SlotID) return; } - m_PoolItems[SlotID].TimeStamp = get_server_start_time(); + m_PoolItems[SlotID].TimeStamp = timer::start_time; roeutils::event(ROE_EVENT::ROE_LOOTITEM, winner, RoeDatagram("itemid", m_PoolItems[SlotID].ID)); @@ -598,7 +598,7 @@ void CTreasurePool::treasureError(CCharEntity* winner, uint8 SlotID) return; } - m_PoolItems[SlotID].TimeStamp = get_server_start_time(); + m_PoolItems[SlotID].TimeStamp = timer::start_time; for (const auto& member : m_Members) { @@ -618,7 +618,7 @@ void CTreasurePool::treasureLost(uint8 SlotID) return; } - m_PoolItems[SlotID].TimeStamp = get_server_start_time(); + m_PoolItems[SlotID].TimeStamp = timer::start_time; for (const auto& member : m_Members) { diff --git a/src/map/treasure_pool.h b/src/map/treasure_pool.h index 458bbbb16d2..4b408862f81 100644 --- a/src/map/treasure_pool.h +++ b/src/map/treasure_pool.h @@ -56,9 +56,9 @@ struct LotInfo struct TreasurePoolItem { - uint16 ID; - uint8 SlotID; - time_point TimeStamp; + uint16 ID; + uint8 SlotID; + timer::time_point TimeStamp; std::vector Lotters; @@ -93,19 +93,19 @@ class CTreasurePool void updatePool(CCharEntity* PChar); void flush(); - void checkItems(time_point); + void checkItems(timer::time_point); void treasureWon(CCharEntity* winner, uint8 SlotID); void treasureError(CCharEntity* winner, uint8 SlotID); void treasureLost(uint8 SlotID); private: - time_point m_Tick; - uint8 m_count; + timer::time_point m_Tick; + uint8 m_count; TreasurePoolType m_TreasurePoolType; - void checkTreasureItem(time_point tick, uint8 SlotID); + void checkTreasureItem(timer::time_point tick, uint8 SlotID); std::array m_PoolItems; std::vector m_Members; diff --git a/src/map/utils/auctionutils.cpp b/src/map/utils/auctionutils.cpp index c90616540b4..e7097b201d0 100644 --- a/src/map/utils/auctionutils.cpp +++ b/src/map/utils/auctionutils.cpp @@ -152,9 +152,9 @@ void auctionutils::OpenListOfSales(CCharEntity* PChar, uint8 action, uint16 item { TracyZoneScoped; - const uint32 curTick = gettick(); + const auto curTick = timer::now(); - if (curTick - PChar->m_AHHistoryTimestamp > 5000) + if (curTick - PChar->m_AHHistoryTimestamp > 5s) { PChar->m_ah_history.clear(); PChar->m_AHHistoryTimestamp = curTick; @@ -263,7 +263,7 @@ void auctionutils::ProofOfPurchase(CCharEntity* PChar, uint8 action, uint32 pric } if (!db::preparedStmt("INSERT INTO auction_house(itemid, stack, seller, seller_name, date, price) VALUES(?, ?, ?, ?, ?, ?)", - PItem->getID(), quantity == 0, PChar->id, PChar->getName(), (uint32)time(nullptr), price)) + PItem->getID(), quantity == 0, PChar->id, PChar->getName(), earth_time::timestamp(), price)) { ShowErrorFmt("AH: Cannot insert item {} to database", PItem->getName()); PChar->pushPacket(action, 197, 0, 0, 0, 0); // failed to place up @@ -309,7 +309,7 @@ void auctionutils::PurchasingItems(CCharEntity* PChar, uint8 action, uint32 pric { const auto rset = db::preparedStmt("UPDATE auction_house SET buyer_name = ?, sale = ?, sell_date = ? WHERE itemid = ? AND buyer_name IS NULL " "AND stack = ? AND price <= ? ORDER BY price LIMIT 1", - PChar->getName(), price, (uint32)time(nullptr), itemid, quantity == 0, price); + PChar->getName(), price, earth_time::timestamp(), itemid, quantity == 0, price); if (rset && rset->rowsAffected()) { uint8 SlotID = charutils::AddItem(PChar, LOC_INVENTORY, itemid, (quantity == 0 ? PItem->getStackSize() : 1)); diff --git a/src/map/utils/battleutils.cpp b/src/map/utils/battleutils.cpp index 0ac9d5c95df..84dc9b9adcd 100644 --- a/src/map/utils/battleutils.cpp +++ b/src/map/utils/battleutils.cpp @@ -211,8 +211,8 @@ namespace battleutils PMobSkill->setAoe(_sql->GetIntData(3)); PMobSkill->setAoeRadius(_sql->GetIntData(4)); PMobSkill->setDistance(_sql->GetFloatData(5)); - PMobSkill->setAnimationTime(_sql->GetIntData(6)); - PMobSkill->setActivationTime(_sql->GetIntData(7)); + PMobSkill->setAnimationTime(std::chrono::milliseconds(_sql->GetIntData(6))); + PMobSkill->setActivationTime(std::chrono::milliseconds(_sql->GetIntData(7))); PMobSkill->setValidTargets(_sql->GetIntData(8)); PMobSkill->setFlag(_sql->GetIntData(9)); PMobSkill->setParam(_sql->GetIntData(10)); @@ -265,8 +265,8 @@ namespace battleutils PPetSkill->setName(_sql->GetStringData(2)); PPetSkill->setAoe(_sql->GetIntData(3)); PPetSkill->setDistance(_sql->GetFloatData(4)); - PPetSkill->setAnimationTime(_sql->GetIntData(5)); - PPetSkill->setActivationTime(_sql->GetIntData(6)); + PPetSkill->setAnimationTime(std::chrono::milliseconds(_sql->GetIntData(5))); + PPetSkill->setActivationTime(std::chrono::milliseconds(_sql->GetIntData(6))); PPetSkill->setValidTargets(_sql->GetIntData(7)); PPetSkill->setMsg(_sql->GetIntData(8)); PPetSkill->setFlag(_sql->GetIntData(9)); @@ -663,7 +663,7 @@ namespace battleutils // matching day 10% bonus, matching weather 10% or 25% for double weather float dBonus = 1.0; float resist = 1.0; - uint32 WeekDay = CVanaTime::getInstance()->getWeekday(); + uint32 WeekDay = static_cast(vanadiel_time::get_weekday()); WEATHER weather = GetWeather(PAttacker, false); DAYTYPE strongDay[8] = { FIRESDAY, ICEDAY, WINDSDAY, EARTHSDAY, LIGHTNINGDAY, WATERSDAY, LIGHTSDAY, DARKSDAY }; @@ -1108,7 +1108,7 @@ namespace battleutils { if (!PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_CURSE)) { - PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_CURSE, EFFECT_CURSE, 15, 0, 180)); + PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_CURSE, EFFECT_CURSE, 15, 0s, 3min)); } break; } @@ -1116,7 +1116,7 @@ namespace battleutils { if (xirand::GetRandomNumber(100) < 20 + lvlDiff && !PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_PARALYSIS)) { - PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_PARALYSIS, EFFECT_PARALYSIS, 20, 0, 30)); + PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_PARALYSIS, EFFECT_PARALYSIS, 20, 0s, 30s)); } break; } @@ -1124,7 +1124,7 @@ namespace battleutils { if (xirand::GetRandomNumber(100) < 30 + lvlDiff && !PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_STUN)) { - PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_STUN, EFFECT_STUN, 1, 0, 3)); + PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_STUN, EFFECT_STUN, 1, 0s, 3s)); } break; } @@ -1273,17 +1273,17 @@ namespace battleutils } if (PDefender->objtype == TYPE_PC) { - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(previous_daze, 0, previous_daze_power, 0, 10, PAttacker->id), EffectNotice::Silent); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(previous_daze, 0, previous_daze_power, 0s, 10s, PAttacker->id), EffectNotice::Silent); } else { if (previous_daze == EFFECT_DRAIN_DAZE && PDefender->m_EcoSystem != ECOSYSTEM::UNDEAD) { - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DRAIN_DAZE, 0, previous_daze_power, 0, 10, PAttacker->id), EffectNotice::Silent); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DRAIN_DAZE, 0, previous_daze_power, 0s, 10s, PAttacker->id), EffectNotice::Silent); } else { - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(previous_daze, 0, previous_daze_power, 0, 10, PAttacker->id), EffectNotice::Silent); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(previous_daze, 0, previous_daze_power, 0s, 10s, PAttacker->id), EffectNotice::Silent); } } } @@ -1585,7 +1585,7 @@ namespace battleutils { Action->additionalEffect = SUBEFFECT_HASTE; // Ability haste added in scripts\globals\effects\haste_samba_haste_effect.lua - PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HASTE_SAMBA_HASTE, 0, power, 0, 10)); + PAttacker->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_HASTE_SAMBA_HASTE, 0, power, 0s, 10s)); // Status effect removed in CAttackRound constructor (i.e. after next attack round is calculated) } } @@ -3757,7 +3757,7 @@ namespace battleutils if (PSCEffect == nullptr && PCBEffect == nullptr) { // No effect exists, apply an effect using the weaponskill ID as the power with a tier of 0. - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SKILLCHAIN, 0, combined_properties, 0, 10, 0, 0, 0)); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SKILLCHAIN, 0, combined_properties, 0s, 10s, 0, 0, 0)); return SUBEFFECT_NONE; } else @@ -3768,7 +3768,7 @@ namespace battleutils // Chainbound active on target if (PCBEffect) { - if (PCBEffect->GetStartTime() + 2s < server_clock::now()) + if (PCBEffect->GetStartTime() + 2s < timer::now()) { // Konzen-Ittai if (PCBEffect->GetPower() > 1) @@ -3788,12 +3788,12 @@ namespace battleutils skillchain = FormSkillchain(resonanceProperties, skillProperties); } - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SKILLCHAIN, 0, combined_properties, 0, 10, 0, 0, 0)); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SKILLCHAIN, 0, combined_properties, 0s, 10s, 0, 0, 0)); PDefender->StatusEffectContainer->DelStatusEffect(EFFECT_CHAINBOUND); PSCEffect = PDefender->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN, 0); } // Previous effect exists - else if (PSCEffect && PSCEffect->GetStartTime() + 3s < server_clock::now()) + else if (PSCEffect && PSCEffect->GetStartTime() + 3s < timer::now()) { if (PSCEffect->GetTier() == 0) { @@ -3834,8 +3834,8 @@ namespace battleutils if (skillchain != SC_NONE) { - PSCEffect->SetStartTime(server_clock::now()); - PSCEffect->SetDuration(PSCEffect->GetDuration() - 1000); + PSCEffect->SetStartTime(timer::now()); + PSCEffect->SetDuration(PSCEffect->GetDuration() - 1s); PSCEffect->SetTier(GetSkillchainTier(skillchain)); PSCEffect->SetPower(skillchain); PSCEffect->SetSubPower(std::min(PSCEffect->GetSubPower() + 1, 5)); // Linked, limited to 5 @@ -3854,8 +3854,8 @@ namespace battleutils return (SUBEFFECT)GetSkillchainSubeffect(skillchain); } - PSCEffect->SetStartTime(server_clock::now()); - PSCEffect->SetDuration(10000); + PSCEffect->SetStartTime(timer::now()); + PSCEffect->SetDuration(10s); PSCEffect->SetTier(0); PSCEffect->SetPower(combined_properties); PSCEffect->SetSubPower(0); @@ -4669,7 +4669,7 @@ namespace battleutils return shotCount; } - void applyCharm(CBattleEntity* PCharmer, CBattleEntity* PVictim, duration charmTime) + void applyCharm(CBattleEntity* PCharmer, CBattleEntity* PVictim, timer::duration charmTime) { PVictim->isCharmed = true; @@ -4691,7 +4691,7 @@ namespace battleutils // set the mobs ai to petAi PCharmer->PPet->PAI->SetController(std::make_unique(PMob)); - PCharmer->PPet->charmTime = server_clock::now() + charmTime; + PCharmer->PPet->charmTime = timer::now() + charmTime; // this will make him transition back to roaming if sleeping PCharmer->PPet->animation = ANIMATION_NONE; @@ -5333,13 +5333,13 @@ namespace battleutils if (effectScarDel && effectScarDel->GetPower() == 0) { // Damage to Max HP Ratio - int8 bonus = std::floor(((damage * 100) / PDefender->GetMaxHP()) / 2); - int8 jpValue = effectScarDel->GetSubPower(); - uint32 duration = 90 + jpValue; + int8 bonus = std::floor(((damage * 100) / PDefender->GetMaxHP()) / 2); + int8 jpValue = effectScarDel->GetSubPower(); + auto duration = 90s + std::chrono::seconds(jpValue); // Convert status effect from "Absorb damage" mode to "Provide damage bonus" mode PDefender->StatusEffectContainer->DelStatusEffectSilent(EFFECT_SCARLET_DELIRIUM); - PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SCARLET_DELIRIUM_1, EFFECT_SCARLET_DELIRIUM_1, bonus, 0, duration), EffectNotice::Silent); + PDefender->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_SCARLET_DELIRIUM_1, EFFECT_SCARLET_DELIRIUM_1, bonus, 0s, duration), EffectNotice::Silent); } } @@ -5467,7 +5467,7 @@ namespace battleutils ELEMENT GetDayElement() { - DAYTYPE weekday = (DAYTYPE)CVanaTime::getInstance()->getWeekday(); + DAYTYPE weekday = static_cast(vanadiel_time::get_weekday()); switch (weekday) { case FIRESDAY: @@ -5829,7 +5829,7 @@ namespace battleutils if (recast->ID != 0 && recast->ID != 196) { resetCandidateList.push_back(i); - if (recast->RecastTime > 0) + if (recast->RecastTime > 0s) { activeCooldownList.push_back(i); } @@ -6119,12 +6119,12 @@ namespace battleutils return found; } - uint32 CalculateSpellCastTime(CBattleEntity* PEntity, CMagicState* PMagicState) + timer::duration CalculateSpellCastTime(CBattleEntity* PEntity, CMagicState* PMagicState) { CSpell* PSpell = PMagicState->GetSpell(); if (PSpell == nullptr) { - return 0; + return 0s; } // Check Quick Magic procs @@ -6132,16 +6132,16 @@ namespace battleutils if (xirand::GetRandomNumber(100) < quickMagicRate) { PMagicState->SetInstantCast(true); - return 0; + return 0s; } - bool applyArts = true; - uint32 base = PSpell->getCastTime(); - uint32 cast = base; + bool applyArts = true; + auto base = PSpell->getCastTime(); + auto cast = base; if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_HASSO, EFFECT_SEIGAN })) { - cast = (uint32)(cast * 1.5f); + cast = std::chrono::floor(cast * 1.5); } if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) @@ -6163,7 +6163,7 @@ namespace battleutils bonus += PChar->PJobPoints->GetJobPointValue(JP_STRATEGEM_EFFECT_II); } - cast -= (uint32)(base * ((100 - (50 + bonus)) / 100.0f)); + cast -= std::chrono::floor(base * ((100 - (50 + bonus)) / 100.0f)); applyArts = false; } // Add Black & Dark Magic Casting Time -% bonus to Bio, Absorbs, Drain, Aspir, Dread Spikes, Stun, Tractor, Endark @@ -6171,7 +6171,7 @@ namespace battleutils // https://www.bg-wiki.com/ffxi/Fallen%27s_Burgeonet else if (PSpell->getSkillType() == SKILLTYPE::SKILL_DARK_MAGIC) { - cast = (uint32)(cast * (1.0f + ((PEntity->getMod(Mod::BLACK_MAGIC_CAST) + PEntity->getMod(Mod::DARK_MAGIC_CAST)) / 100.0f))); + cast = std::chrono::floor(cast * (1.0f + ((PEntity->getMod(Mod::BLACK_MAGIC_CAST) + PEntity->getMod(Mod::DARK_MAGIC_CAST)) / 100.0f))); applyArts = false; } else if (applyArts) @@ -6179,11 +6179,11 @@ namespace battleutils if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_DARK_ARTS, EFFECT_ADDENDUM_BLACK })) { // Add any "Grimoire: Reduces spellcasting time" bonuses - cast = (uint32)(cast * (1.0f + (PEntity->getMod(Mod::BLACK_MAGIC_CAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); + cast = std::chrono::floor(cast * (1.0f + (PEntity->getMod(Mod::BLACK_MAGIC_CAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); } else { - cast = (uint32)(cast * (1.0f + PEntity->getMod(Mod::BLACK_MAGIC_CAST) / 100.0f)); + cast = std::chrono::floor(cast * (1.0f + PEntity->getMod(Mod::BLACK_MAGIC_CAST) / 100.0f)); } } } @@ -6206,7 +6206,7 @@ namespace battleutils bonus += PChar->PJobPoints->GetJobPointValue(JP_STRATEGEM_EFFECT_II); } - cast -= (uint32)(base * ((100 - (50 + bonus)) / 100.0f)); + cast -= std::chrono::floor(base * ((100 - (50 + bonus)) / 100.0f)); applyArts = false; } else if (applyArts) @@ -6214,31 +6214,31 @@ namespace battleutils if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_LIGHT_ARTS, EFFECT_ADDENDUM_WHITE })) { // Add any "Grimoire: Reduces spellcasting time" bonuses - cast = (uint32)(cast * (1.0f + (PEntity->getMod(Mod::WHITE_MAGIC_CAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); + cast = std::chrono::floor(cast * (1.0f + (PEntity->getMod(Mod::WHITE_MAGIC_CAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); } else { - cast = (uint32)(cast * (1.0f + PEntity->getMod(Mod::WHITE_MAGIC_CAST) / 100.0f)); + cast = std::chrono::floor(cast * (1.0f + PEntity->getMod(Mod::WHITE_MAGIC_CAST) / 100.0f)); } } } else if (PSpell->getSpellGroup() == SPELLGROUP_SUMMONING) { - int32 amount = 1000 * PEntity->getMod(Mod::SUMMONING_MAGIC_CAST); + auto amount = 1000ms * PEntity->getMod(Mod::SUMMONING_MAGIC_CAST); if (PEntity->objtype == TYPE_PC) { auto* PChar = static_cast(PEntity); - amount += static_cast(base * 0.01 * PChar->PMeritPoints->GetMeritValue(MERIT_SUMMONING_MAGIC_CAST_TIME, PChar)); + amount += std::chrono::floor(base * 0.01 * PChar->PMeritPoints->GetMeritValue(MERIT_SUMMONING_MAGIC_CAST_TIME, PChar)); } - if (static_cast(cast) > amount) + if (cast > amount) { - cast -= static_cast(std::max(amount, 0)); + cast -= std::max(amount, 0s); } else { - cast = 0; + cast = 0s; } } else if (PSpell->getSpellGroup() == SPELLGROUP_SONG) @@ -6255,23 +6255,23 @@ namespace battleutils if (PEntity->objtype == TYPE_PC && xirand::GetRandomNumber(100) < ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_NIGHTINGALE, (CCharEntity*)PEntity) - 25) { - return 0; + return 0s; } - cast = (uint32)(cast * 0.5f); + cast = std::chrono::floor(cast * 0.5f); } if (PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_TROUBADOUR)) { - cast = (uint32)(cast * 1.5f); + cast = std::chrono::floor(cast * 1.5f); } uint16 songcasting = PEntity->getMod(Mod::SONG_SPELLCASTING_TIME); - cast = (uint32)(cast * (1.0f - ((songcasting > 50 ? 50 : songcasting) / 100.0f))); + cast = std::chrono::floor(cast * (1.0f - ((songcasting > 50 ? 50 : songcasting) / 100.0f))); } else if (PSpell->getSpellGroup() == SPELLGROUP_NINJUTSU) { if (PEntity->objtype == TYPE_PC) { uint8 jpValue = static_cast(PEntity)->PJobPoints->GetJobPointValue(JP_NINJITSU_CAST_TIME_BONUS); - cast = static_cast(cast * (1.0f - (0.03f * jpValue))); + cast = std::chrono::floor(cast * (1.0f - (0.03f * jpValue))); } } @@ -6306,7 +6306,7 @@ namespace battleutils float sumFastCast = std::clamp((float)(fastCast + uncappedFastCast + inspirationFastCast), -100.f, 100.f); - return (uint32)(cast * ((100.0f - sumFastCast) / 100.0f)); + return std::chrono::floor(cast * ((100.0f - sumFastCast) / 100.0f)); } uint16 CalculateSpellCost(CBattleEntity* PEntity, CSpell* PSpell) @@ -6373,15 +6373,15 @@ namespace battleutils return std::clamp(cost, 0, 9999); } - uint32 CalculateSpellRecastTime(CBattleEntity* PEntity, CSpell* PSpell) + timer::duration CalculateSpellRecastTime(CBattleEntity* PEntity, CSpell* PSpell) { if (PSpell == nullptr) { - return 0; + return 0s; } - uint32 base = PSpell->getRecastTime(); - int32 recast = base; + auto base = PSpell->getRecastTime(); + auto recast = base; // get Fast Cast reduction, caps at 80%/2 = 40% reduction in recast -- https://www.bg-wiki.com/ffxi/Fast_Cast float fastCastReduction = std::clamp(static_cast(PEntity->getMod(Mod::FASTCAST)) / 2.0f, 0.0f, 40.0f); @@ -6389,57 +6389,58 @@ namespace battleutils float inspirationRecastReduction = static_cast(PEntity->getMod(Mod::INSPIRATION_FAST_CAST)) / 2.0f; // Apply Fast Cast & Inspiration - recast = static_cast(recast * ((100.0f - (fastCastReduction + inspirationRecastReduction)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f - (fastCastReduction + inspirationRecastReduction)) / 100.0f)); // Apply Haste (Magic and Gear) int32 hasteMagic = std::clamp(PEntity->getMod(Mod::HASTE_MAGIC), -10000, 4375); // 43.75% cap -- handle 100% slow for weakness int32 hasteGear = std::clamp(PEntity->getMod(Mod::HASTE_GEAR), -2500, 2500); // 25% int32 haste = hasteMagic + hasteGear; - recast = static_cast(recast * ((10000.0f - haste) / 10000.0f)); + recast = std::chrono::floor(recast * ((10000.0f - haste) / 10000.0f)); if (PSpell->getSpellGroup() == SPELLGROUP_SONG) { if (PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_NIGHTINGALE)) { - recast = static_cast(recast * 0.5f); + recast = std::chrono::floor(recast * 0.5f); } // The following modifiers are not multiplicative - as such they must be applied last. if (PEntity->objtype == TYPE_PC) { + auto* PChar = static_cast(PEntity); if (PSpell->getID() == SpellID::Magic_Finale) // apply Finale recast merits { - recast -= ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_FINALE_RECAST, (CCharEntity*)PEntity) * 1000; + recast -= std::chrono::seconds(PChar->PMeritPoints->GetMeritValue(MERIT_FINALE_RECAST, PChar)); } if (PSpell->getID() == SpellID::Foe_Lullaby || PSpell->getID() == SpellID::Foe_Lullaby_II || PSpell->getID() == SpellID::Horde_Lullaby || PSpell->getID() == SpellID::Horde_Lullaby_II) // apply Lullaby recast merits { - recast -= ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_LULLABY_RECAST, (CCharEntity*)PEntity) * 1000; + recast -= std::chrono::seconds(PChar->PMeritPoints->GetMeritValue(MERIT_LULLABY_RECAST, PChar)); } } - recast -= PEntity->getMod(Mod::SONG_RECAST_DELAY) * 1000; + recast -= std::chrono::seconds(PEntity->getMod(Mod::SONG_RECAST_DELAY)); } if (PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_COMPOSURE)) { - recast = static_cast(recast * 1.25f); + recast = std::chrono::floor(recast * 1.25f); } if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_HASSO, EFFECT_SEIGAN })) { - recast = static_cast(recast * 1.5f); + recast = std::chrono::floor(recast * 1.5f); } - recast = std::max(recast, static_cast(base * 0.2f)); + recast = std::max(recast, std::chrono::floor(base * 0.2f)); if (PSpell->getSkillType() == SKILLTYPE::SKILL_ELEMENTAL_MAGIC) { - recast = static_cast(recast * ((100.0f + PEntity->getMod(Mod::ELEMENTAL_MAGIC_RECAST)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f + PEntity->getMod(Mod::ELEMENTAL_MAGIC_RECAST)) / 100.0f)); } if (PSpell->getSkillType() == SKILLTYPE::SKILL_BLUE_MAGIC) { - recast = static_cast(recast * ((100.0f + PEntity->getMod(Mod::BLUE_MAGIC_RECAST)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f + PEntity->getMod(Mod::BLUE_MAGIC_RECAST)) / 100.0f)); } // Light/Dark arts recast bonus/penalties applies after other bonuses @@ -6459,28 +6460,28 @@ namespace battleutils else if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_DARK_ARTS, EFFECT_ADDENDUM_BLACK })) { // Add any "Grimoire: Reduces spellcasting time" bonuses + Dark Arts bonus - recast = static_cast(recast * ((100.0f + PEntity->getMod(Mod::BLACK_MAGIC_RECAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f + PEntity->getMod(Mod::BLACK_MAGIC_RECAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); } else { - recast = static_cast(recast * ((100.0f + PEntity->getMod(Mod::BLACK_MAGIC_RECAST)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f + PEntity->getMod(Mod::BLACK_MAGIC_RECAST)) / 100.0f)); } - recast = std::max(recast, static_cast(base * 0.2f)); // recap to 80% + recast = std::max(recast, std::chrono::floor(base * 0.2f)); // recap to 80% // https://www.bg-wiki.com/ffxi/Alacrity if (PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY)) { - recast = static_cast(recast * 0.60); // 40% reduction from Alacrity alone - recast = std::max(recast, static_cast(base * 0.2f)); // recap to 80% + recast = std::chrono::floor(recast * 0.60); // 40% reduction from Alacrity alone + recast = std::max(recast, std::chrono::floor(base * 0.2f)); // recap to 80% // Only apply bonus mod if the spell element matches the weather, this is allowed to go over the 80% cap to a 90% cap. if (battleutils::WeatherMatchesElement(battleutils::GetWeather(PEntity, false), static_cast(PSpell->getElement()))) { uint16 bonus = PEntity->getMod(Mod::ALACRITY_CELERITY_EFFECT); - recast = static_cast(recast * ((100 - bonus) / 100.0f)); - recast = std::max(recast, static_cast(base * 0.1f)); // cap to 90% reduction + recast = std::chrono::floor(recast * ((100 - bonus) / 100.0f)); + recast = std::max(recast, std::chrono::floor(base * 0.1f)); // cap to 90% reduction } } } @@ -6501,35 +6502,35 @@ namespace battleutils if (PEntity->StatusEffectContainer->HasStatusEffect({ EFFECT_LIGHT_ARTS, EFFECT_ADDENDUM_WHITE })) { // Add any "Grimoire: Reduces spellcasting time" bonuses + Light Arts bonus - recast = static_cast(recast * ((100.f + PEntity->getMod(Mod::WHITE_MAGIC_RECAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.f + PEntity->getMod(Mod::WHITE_MAGIC_RECAST) + PEntity->getMod(Mod::GRIMOIRE_SPELLCASTING)) / 100.0f)); } else { - recast = static_cast(recast * ((100.0f + PEntity->getMod(Mod::WHITE_MAGIC_RECAST)) / 100.0f)); + recast = std::chrono::floor(recast * ((100.0f + PEntity->getMod(Mod::WHITE_MAGIC_RECAST)) / 100.0f)); } - recast = std::max(recast, static_cast(base * 0.2f)); // recap to 80% + recast = std::max(recast, std::chrono::floor(base * 0.2f)); // recap to 80% // https://www.bg-wiki.com/ffxi/Celerity if (PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_CELERITY)) { - recast = static_cast(recast * 0.60); // 40% reduction from Celerity alone - recast = std::max(recast, static_cast(base * 0.2f)); // recap to 80% + recast = std::chrono::floor(recast * 0.60); // 40% reduction from Celerity alone + recast = std::max(recast, std::chrono::floor(base * 0.2f)); // recap to 80% // Only apply bonus mod if the spell element matches the weather, this is allowed to go over the 80% cap to a 90% cap. if (battleutils::WeatherMatchesElement(battleutils::GetWeather(PEntity, false), static_cast(PSpell->getElement()))) { uint16 bonus = PEntity->getMod(Mod::ALACRITY_CELERITY_EFFECT); - recast = static_cast(recast * ((100 - bonus) / 100.0f)); - recast = std::max(recast, static_cast(base * 0.1f)); // cap to 90% reduction + recast = std::chrono::floor(recast * ((100 - bonus) / 100.0f)); + recast = std::max(recast, std::chrono::floor(base * 0.1f)); // cap to 90% reduction } } } - recast = std::max(recast, 0); + recast = std::max(recast, 0s); - return recast / 1000; + return recast; } // Calculate TP generated by spell for Occult Acumen trait diff --git a/src/map/utils/battleutils.h b/src/map/utils/battleutils.h index ce308da0430..c0d89f57ce8 100644 --- a/src/map/utils/battleutils.h +++ b/src/map/utils/battleutils.h @@ -195,7 +195,7 @@ namespace battleutils bool HasNinjaTool(CBattleEntity* PEntity, CSpell* PSpell, bool ConsumeTool); - void applyCharm(CBattleEntity* PCharmer, CBattleEntity* PVictim, duration charmTime = 0s); + void applyCharm(CBattleEntity* PCharmer, CBattleEntity* PVictim, timer::duration charmTime = 0s); void unCharm(CBattleEntity* PEntity); uint16 doSoulEaterEffect(CCharEntity* m_PChar, uint32 damage); @@ -256,13 +256,13 @@ namespace battleutils void AddTraits(CBattleEntity* PEntity, TraitList_t* TraitList, uint8 level); bool HasClaim(CBattleEntity* PEntity, CBattleEntity* PTarget); - uint32 CalculateSpellCastTime(CBattleEntity*, CMagicState*); - uint16 CalculateSpellCost(CBattleEntity*, CSpell*); - uint32 CalculateSpellRecastTime(CBattleEntity*, CSpell*); - int16 CalculateSpellTP(CBattleEntity* PEntity, CSpell* PSpell); - int16 CalculateWeaponSkillTP(CBattleEntity*, CWeaponSkill*, int16); - bool RemoveAmmo(CCharEntity*, int quantity = 1); - int32 GetMeritValue(CBattleEntity*, MERIT_TYPE); + timer::duration CalculateSpellCastTime(CBattleEntity*, CMagicState*); + uint16 CalculateSpellCost(CBattleEntity*, CSpell*); + timer::duration CalculateSpellRecastTime(CBattleEntity*, CSpell*); + int16 CalculateSpellTP(CBattleEntity* PEntity, CSpell* PSpell); + int16 CalculateWeaponSkillTP(CBattleEntity*, CWeaponSkill*, int16); + bool RemoveAmmo(CCharEntity*, int quantity = 1); + int32 GetMeritValue(CBattleEntity*, MERIT_TYPE); int32 GetScaledItemModifier(CBattleEntity*, CItemEquipment*, Mod); DAMAGE_TYPE GetSpikesDamageType(SUBEFFECT spikesType); diff --git a/src/map/utils/charutils.cpp b/src/map/utils/charutils.cpp index 43f41998c71..75baf9ca753 100644 --- a/src/map/utils/charutils.cpp +++ b/src/map/utils/charutils.cpp @@ -430,11 +430,11 @@ namespace charutils db::extractFromBlob(rset, "campaign", PChar->m_campaignLog); db::extractFromBlob(rset, "eminence", PChar->m_eminenceLog); - PChar->SetPlayTime(rset->get("playtime")); + PChar->SetPlayTime(std::chrono::seconds(rset->get("playtime"))); PChar->profile.campaign_allegiance = rset->get("campaign_allegiance"); PChar->setStyleLocked(rset->get("isstylelocked") == 1); PChar->SetMoghancement(rset->get("moghancement")); - PChar->lastOnline = rset->get("lastonline"); + PChar->lastOnline = earth_time::time_point(std::chrono::seconds(rset->get("lastonline"))); PChar->search.language = rset->get("languages"); PChar->m_GMlevel = rset->get("gmlevel"); @@ -705,8 +705,9 @@ namespace charutils PChar->petZoningInfo.petType = static_cast(rset->get("pet_type")); PChar->petZoningInfo.petLevel = rset->get("pet_level"); PChar->petZoningInfo.respawnPet = true; - PChar->petZoningInfo.jugSpawnTime = static_cast(PChar->getCharVar("jugpet-spawn-time")); - PChar->petZoningInfo.jugDuration = static_cast(PChar->getCharVar("jugpet-duration-seconds")); + auto jugTimestamp = static_cast(PChar->getCharVar("jugpet-spawn-time")); + PChar->petZoningInfo.jugSpawnTime = timer::from_utc(earth_time::time_point(std::chrono::seconds(jugTimestamp))); + PChar->petZoningInfo.jugDuration = std::chrono::seconds(PChar->getCharVar("jugpet-duration-seconds")); // clear the charvars used for jug state PChar->clearCharVarsWithPrefix("jugpet-"); @@ -735,12 +736,12 @@ namespace charutils { while (rset->next()) { - uint32 cast_time = rset->get("time"); - uint32 recast = rset->get("recast"); - time_t now = time(nullptr); - uint32 chargeTime = 0; - uint8 maxCharges = 0; - Charge_t* charge = ability::GetCharge(PChar, rset->get("id")); + auto now = timer::now(); + auto cast_time = timer::from_utc(earth_time::time_point(std::chrono::seconds(rset->get("time")))); + auto recast = std::chrono::seconds(rset->get("recast")); + timer::duration chargeTime = 0s; + uint8 maxCharges = 0; + Charge_t* charge = ability::GetCharge(PChar, rset->get("id")); if (charge != nullptr) { chargeTime = charge->chargeTime; @@ -748,7 +749,7 @@ namespace charutils } if (now < cast_time + recast) { - PChar->PRecastContainer->Load(RECAST_ABILITY, rset->get("id"), (cast_time + recast - (uint32)now), chargeTime, maxCharges); + PChar->PRecastContainer->Load(RECAST_ABILITY, rset->get("id"), (cast_time + recast - now), chargeTime, maxCharges); } } } @@ -972,6 +973,13 @@ namespace charutils PItem->setSignature(EncodedString); } + if (auto PItemUsable = dynamic_cast(PItem)) + { + uint32 useTime = 0; + std::memcpy(&useTime, PItemUsable->m_extra + 0x04, sizeof(useTime)); + PItemUsable->setLastUseTime(timer::now() - std::chrono::seconds(earth_time::vanadiel_timestamp() - useTime)); + } + if (PItem->isType(ITEM_FURNISHING) && (PItem->getLocationID() == LOC_MOGSAFE || PItem->getLocationID() == LOC_MOGSAFE2)) { if (((CItemFurnishing*)PItem)->isInstalled()) // Check if furniture (furnishing) item is actually installed @@ -2753,9 +2761,9 @@ namespace charutils } if (PItem->isType(ITEM_USABLE) && ((CItemUsable*)PItem)->getCurrentCharges() != 0) { - PItem->setAssignTime(CVanaTime::getInstance()->getVanaTime()); - PChar->PRecastContainer->Add(RECAST_ITEM, slotID << 8 | containerID, - PItem->getReuseTime() / 1000); // add recast timer to Recast List from any bag + PItem->setAssignTime(timer::now()); + // add recast timer to Recast List from any bag + PChar->PRecastContainer->Add(RECAST_ITEM, slotID << 8 | containerID, PItem->getReuseTime()); // Do not forget to update the timer when equipping the subject @@ -3097,17 +3105,17 @@ namespace charutils if (PAbility->getID() < ABILITY_HEALING_RUBY && PAbility->getID() != ABILITY_PET_COMMANDS && CheckAbilityAddtype(PChar, PAbility)) { addAbility(PChar, PAbility->getID()); - Charge_t* charge = ability::GetCharge(PChar, PAbility->getRecastId()); - auto chargeTime = 0; - auto maxCharges = 0; + Charge_t* charge = ability::GetCharge(PChar, PAbility->getRecastId()); + timer::duration chargeTime = 0s; + auto maxCharges = 0; if (charge) { - chargeTime = charge->chargeTime - PChar->PMeritPoints->GetMeritValue((MERIT_TYPE)charge->merit, PChar); + chargeTime = charge->chargeTime - std::chrono::seconds(PChar->PMeritPoints->GetMeritValue((MERIT_TYPE)charge->merit, PChar)); maxCharges = charge->maxCharges; } if (!PChar->PRecastContainer->Has(RECAST_ABILITY, PAbility->getRecastId())) { - PChar->PRecastContainer->Add(RECAST_ABILITY, PAbility->getRecastId(), 0, chargeTime, maxCharges); + PChar->PRecastContainer->Add(RECAST_ABILITY, PAbility->getRecastId(), 0s, chargeTime, maxCharges); } } } @@ -3137,17 +3145,17 @@ namespace charutils if (PAbility->getID() != ABILITY_PET_COMMANDS && CheckAbilityAddtype(PChar, PAbility) && !(PAbility->getAddType() & ADDTYPE_MAIN_ONLY)) { addAbility(PChar, PAbility->getID()); - Charge_t* charge = ability::GetCharge(PChar, PAbility->getRecastId()); - auto chargeTime = 0; - auto maxCharges = 0; + Charge_t* charge = ability::GetCharge(PChar, PAbility->getRecastId()); + timer::duration chargeTime = 0s; + auto maxCharges = 0; if (charge) { - chargeTime = charge->chargeTime - PChar->PMeritPoints->GetMeritValue((MERIT_TYPE)charge->merit, PChar); + chargeTime = charge->chargeTime - std::chrono::seconds(PChar->PMeritPoints->GetMeritValue((MERIT_TYPE)charge->merit, PChar)); maxCharges = charge->maxCharges; } if (!PChar->PRecastContainer->Has(RECAST_ABILITY, PAbility->getRecastId())) { - PChar->PRecastContainer->Add(RECAST_ABILITY, PAbility->getRecastId(), 0, chargeTime, maxCharges); + PChar->PRecastContainer->Add(RECAST_ABILITY, PAbility->getRecastId(), 0s, chargeTime, maxCharges); } } } @@ -4390,7 +4398,7 @@ namespace charutils if (mobCheck > EMobDifficulty::DecentChallenge) { - if (PMember->expChain.chainTime > gettick() || PMember->expChain.chainTime == 0) + if (PMember->expChain.chainTime > timer::now() || PMember->expChain.chainTime == timer::time_point::min()) { chainactive = true; switch (PMember->expChain.chainNumber) @@ -4422,31 +4430,31 @@ namespace charutils { if (PMember->GetMLevel() <= 10) { - PMember->expChain.chainTime = gettick() + 50000; + PMember->expChain.chainTime = timer::now() + 50s; } else if (PMember->GetMLevel() <= 20) { - PMember->expChain.chainTime = gettick() + 100000; + PMember->expChain.chainTime = timer::now() + 100s; } else if (PMember->GetMLevel() <= 30) { - PMember->expChain.chainTime = gettick() + 150000; + PMember->expChain.chainTime = timer::now() + 150s; } else if (PMember->GetMLevel() <= 40) { - PMember->expChain.chainTime = gettick() + 200000; + PMember->expChain.chainTime = timer::now() + 200s; } else if (PMember->GetMLevel() <= 50) { - PMember->expChain.chainTime = gettick() + 250000; + PMember->expChain.chainTime = timer::now() + 250s; } else if (PMember->GetMLevel() <= 60) { - PMember->expChain.chainTime = gettick() + 300000; + PMember->expChain.chainTime = timer::now() + 300s; } else { - PMember->expChain.chainTime = gettick() + 360000; + PMember->expChain.chainTime = timer::now() + 360s; } PMember->expChain.chainNumber = 1; } @@ -4456,25 +4464,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 50000; + PMember->expChain.chainTime = timer::now() + 50s; break; case 1: - PMember->expChain.chainTime = gettick() + 40000; + PMember->expChain.chainTime = timer::now() + 40s; break; case 2: - PMember->expChain.chainTime = gettick() + 30000; + PMember->expChain.chainTime = timer::now() + 30s; break; case 3: - PMember->expChain.chainTime = gettick() + 20000; + PMember->expChain.chainTime = timer::now() + 20s; break; case 4: - PMember->expChain.chainTime = gettick() + 10000; + PMember->expChain.chainTime = timer::now() + 10s; break; case 5: - PMember->expChain.chainTime = gettick() + 6000; + PMember->expChain.chainTime = timer::now() + 6s; break; default: - PMember->expChain.chainTime = gettick() + 2000; + PMember->expChain.chainTime = timer::now() + 2s; break; } } @@ -4483,25 +4491,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 100000; + PMember->expChain.chainTime = timer::now() + 100s; break; case 1: - PMember->expChain.chainTime = gettick() + 80000; + PMember->expChain.chainTime = timer::now() + 80s; break; case 2: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; case 3: - PMember->expChain.chainTime = gettick() + 40000; + PMember->expChain.chainTime = timer::now() + 40s; break; case 4: - PMember->expChain.chainTime = gettick() + 20000; + PMember->expChain.chainTime = timer::now() + 20s; break; case 5: - PMember->expChain.chainTime = gettick() + 8000; + PMember->expChain.chainTime = timer::now() + 8s; break; default: - PMember->expChain.chainTime = gettick() + 4000; + PMember->expChain.chainTime = timer::now() + 4s; break; } } @@ -4510,25 +4518,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 150000; + PMember->expChain.chainTime = timer::now() + 150s; break; case 1: - PMember->expChain.chainTime = gettick() + 120000; + PMember->expChain.chainTime = timer::now() + 120s; break; case 2: - PMember->expChain.chainTime = gettick() + 90000; + PMember->expChain.chainTime = timer::now() + 90s; break; case 3: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; case 4: - PMember->expChain.chainTime = gettick() + 30000; + PMember->expChain.chainTime = timer::now() + 30s; break; case 5: - PMember->expChain.chainTime = gettick() + 10000; + PMember->expChain.chainTime = timer::now() + 10s; break; default: - PMember->expChain.chainTime = gettick() + 5000; + PMember->expChain.chainTime = timer::now() + 5s; break; } } @@ -4537,25 +4545,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 200000; + PMember->expChain.chainTime = timer::now() + 200s; break; case 1: - PMember->expChain.chainTime = gettick() + 160000; + PMember->expChain.chainTime = timer::now() + 160s; break; case 2: - PMember->expChain.chainTime = gettick() + 120000; + PMember->expChain.chainTime = timer::now() + 120s; break; case 3: - PMember->expChain.chainTime = gettick() + 80000; + PMember->expChain.chainTime = timer::now() + 80s; break; case 4: - PMember->expChain.chainTime = gettick() + 40000; + PMember->expChain.chainTime = timer::now() + 40s; break; case 5: - PMember->expChain.chainTime = gettick() + 40000; + PMember->expChain.chainTime = timer::now() + 40s; break; default: - PMember->expChain.chainTime = gettick() + 30000; + PMember->expChain.chainTime = timer::now() + 30s; break; } } @@ -4564,25 +4572,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 250000; + PMember->expChain.chainTime = timer::now() + 250s; break; case 1: - PMember->expChain.chainTime = gettick() + 200000; + PMember->expChain.chainTime = timer::now() + 200s; break; case 2: - PMember->expChain.chainTime = gettick() + 150000; + PMember->expChain.chainTime = timer::now() + 150s; break; case 3: - PMember->expChain.chainTime = gettick() + 100000; + PMember->expChain.chainTime = timer::now() + 100s; break; case 4: - PMember->expChain.chainTime = gettick() + 50000; + PMember->expChain.chainTime = timer::now() + 50s; break; case 5: - PMember->expChain.chainTime = gettick() + 50000; + PMember->expChain.chainTime = timer::now() + 50s; break; default: - PMember->expChain.chainTime = gettick() + 50000; + PMember->expChain.chainTime = timer::now() + 50s; break; } } @@ -4591,25 +4599,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 300000; + PMember->expChain.chainTime = timer::now() + 300s; break; case 1: - PMember->expChain.chainTime = gettick() + 240000; + PMember->expChain.chainTime = timer::now() + 240s; break; case 2: - PMember->expChain.chainTime = gettick() + 180000; + PMember->expChain.chainTime = timer::now() + 180s; break; case 3: - PMember->expChain.chainTime = gettick() + 120000; + PMember->expChain.chainTime = timer::now() + 120s; break; case 4: - PMember->expChain.chainTime = gettick() + 90000; + PMember->expChain.chainTime = timer::now() + 90s; break; case 5: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; default: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; } } @@ -4618,25 +4626,25 @@ namespace charutils switch (PMember->expChain.chainNumber) { case 0: - PMember->expChain.chainTime = gettick() + 360000; + PMember->expChain.chainTime = timer::now() + 360s; break; case 1: - PMember->expChain.chainTime = gettick() + 300000; + PMember->expChain.chainTime = timer::now() + 300s; break; case 2: - PMember->expChain.chainTime = gettick() + 240000; + PMember->expChain.chainTime = timer::now() + 240s; break; case 3: - PMember->expChain.chainTime = gettick() + 165000; + PMember->expChain.chainTime = timer::now() + 165s; break; case 4: - PMember->expChain.chainTime = gettick() + 105000; + PMember->expChain.chainTime = timer::now() + 105s; break; case 5: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; default: - PMember->expChain.chainTime = gettick() + 60000; + PMember->expChain.chainTime = timer::now() + 60s; break; } } @@ -4701,7 +4709,7 @@ namespace charutils // https://ffxiclopedia.fandom.com/wiki/Job_Points#Capacity_Points capacityPoints = 0.0089 * std::pow(levelDiff, 3) + 0.0533 * std::pow(levelDiff, 2) + 3.7439 * levelDiff + 89.7; - if (PMember->capacityChain.chainTime > gettick() || PMember->capacityChain.chainTime == 0) + if (PMember->capacityChain.chainTime > timer::now() || PMember->capacityChain.chainTime == timer::time_point::min()) { chainActive = true; @@ -4713,13 +4721,13 @@ namespace charutils else { // TODO: Capacity Chain Timer is reduced after Chain 30 - PMember->capacityChain.chainTime = gettick() + 30000; + PMember->capacityChain.chainTime = timer::now() + 30s; PMember->capacityChain.chainNumber = 1; } if (chainActive) { - PMember->capacityChain.chainTime = gettick() + 30000; + PMember->capacityChain.chainTime = timer::now() + 30s; } capacityPoints = AddCapacityBonus(PMember, capacityPoints); @@ -5336,7 +5344,7 @@ namespace charutils "LIMIT 1", PChar->m_eminenceLog, PChar->id); - PChar->m_eminenceCache.lastWriteout = static_cast(time(nullptr)); + PChar->m_eminenceCache.lastWriteout = timer::now(); } void SaveCharInventoryCapacity(CCharEntity* PChar) @@ -5511,8 +5519,9 @@ namespace charutils // These two are jug only variables. We should probably move pet char stats into its own table, but in the meantime // we use charvars for jug specific things - PChar->setCharVar("jugpet-spawn-time", static_cast(PChar->petZoningInfo.jugSpawnTime)); - PChar->setCharVar("jugpet-duration-seconds", static_cast(PChar->petZoningInfo.jugDuration)); + auto jugTimestamp = earth_time::timestamp(timer::to_utc(PChar->petZoningInfo.jugSpawnTime)); + PChar->setCharVar("jugpet-spawn-time", jugTimestamp); + PChar->setCharVar("jugpet-duration-seconds", static_cast(timer::count_seconds(PChar->petZoningInfo.jugDuration))); } /************************************************************************ @@ -6023,7 +6032,7 @@ namespace charutils { TracyZoneScoped; auto tstamp = static_cast(PChar->getCharVar("mog-locker-expiry-timestamp")); - if (CVanaTime::getInstance()->getVanaTime() < tstamp) + if (earth_time::vanadiel_timestamp() < tstamp) { return true; } @@ -6092,20 +6101,22 @@ namespace charutils { TracyZoneScoped; - const char* fmtQuery = "UPDATE char_stats SET death = %u WHERE charid = %u LIMIT 1"; - _sql->Query(fmtQuery, PChar->GetSecondsElapsedSinceDeath(), PChar->id); + const char* fmtQuery = "UPDATE char_stats SET death = %u WHERE charid = %u LIMIT 1"; + uint32 secondsSinceDeath = static_cast(timer::count_seconds(PChar->GetTimeSinceDeath())); + _sql->Query(fmtQuery, secondsSinceDeath, PChar->id); } void SavePlayTime(CCharEntity* PChar) { TracyZoneScoped; - uint32 playtime = PChar->GetPlayTime(); + timer::duration playDuration = PChar->GetPlayTime(); + uint32 playtime = static_cast(timer::count_seconds(playDuration)); _sql->Query("UPDATE chars SET playtime = '%u' WHERE charid = '%u' LIMIT 1", playtime, PChar->id); // Removes new player icon if played for more than 240 hours - if (PChar->isNewPlayer() && playtime >= 864000) + if (PChar->isNewPlayer() && playDuration >= 240h) { PChar->playerConfig.NewAdventurerOffFlg = true; PChar->updatemask |= UPDATE_HP; @@ -6351,10 +6362,10 @@ namespace charutils CBattleEntity* PSyncTarget = PChar->PParty->GetSyncTarget(); if (PSyncTarget && PChar->getZone() == PSyncTarget->getZone() && !(PChar->StatusEffectContainer->HasStatusEffect(EFFECT_LEVEL_SYNC)) && PSyncTarget->StatusEffectContainer->HasStatusEffect(EFFECT_LEVEL_SYNC) && - PSyncTarget->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC)->GetDuration() == 0) + PSyncTarget->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC)->GetDuration() == 0s) { PChar->pushPacket(PChar, PChar, 0, PSyncTarget->GetMLevel(), 540); - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PSyncTarget->GetMLevel(), 0, 0), EffectNotice::Silent); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PSyncTarget->GetMLevel(), 0s, 0s), EffectNotice::Silent); PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE); } @@ -6651,7 +6662,7 @@ namespace charutils PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_WEAKNESS); PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_SYNC); - PChar->SetDeathTimestamp(0); + PChar->SetDeathTime(timer::time_point::min()); PChar->health.hp = PChar->GetMaxHP(); PChar->health.mp = PChar->GetMaxMP(); @@ -6783,9 +6794,7 @@ namespace charutils value = rset->get(0); expiry = rset->get(1); - uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); - - if (expiry > 0 && expiry <= currentTimestamp) + if (expiry > 0 && expiry <= earth_time::timestamp()) { value = 0; db::preparedStmt("DELETE FROM char_vars WHERE charid = ? AND varname = ?", charId, varName); @@ -6885,9 +6894,9 @@ namespace charutils PChar->pushPacket(seconds); } - void SendTimerPacket(CCharEntity* PChar, duration dur) + void SendTimerPacket(CCharEntity* PChar, timer::duration dur) { - auto timeLimitSeconds = static_cast(std::chrono::duration_cast(dur).count()); + auto timeLimitSeconds = static_cast(timer::count_seconds(dur)); SendTimerPacket(PChar, timeLimitSeconds); } @@ -6896,19 +6905,19 @@ namespace charutils PChar->pushPacket(); } - time_t getTraverserEpoch(CCharEntity* PChar) + earth_time::time_point getTraverserEpoch(CCharEntity* PChar) { TracyZoneScoped; - auto fmtQuery = "SELECT unix_timestamp(traverser_start) FROM char_unlocks WHERE charid = %u"; + auto fmtQuery = "SELECT UNIX_TIMESTAMP(traverser_start) FROM char_unlocks WHERE charid = %u"; auto ret = _sql->Query(fmtQuery, PChar->id); if (ret != SQL_ERROR && _sql->NumRows() != 0 && _sql->NextRow() == SQL_SUCCESS) { - return _sql->GetUIntData(0); + return earth_time::time_point(std::chrono::seconds(_sql->GetUIntData(0))); } - return 0; + return earth_time::time_point::min(); } // TODO: Perhaps allow for optional argument to support GM Commands @@ -6958,18 +6967,18 @@ namespace charutils { TracyZoneScoped; - auto fmtQuery = "SELECT unix_timestamp(traverser_start), traverser_claimed FROM char_unlocks WHERE charid = %u"; - time_t traverserEpoch = 0; - uint32 traverserClaimed = 0; + auto fmtQuery = "SELECT UNIX_TIMESTAMP(traverser_start), traverser_claimed FROM char_unlocks WHERE charid = %u"; + earth_time::time_point traverserEpoch = earth_time::time_point::min(); + uint32 traverserClaimed = 0; auto ret = _sql->Query(fmtQuery, PChar->id); if (ret != SQL_ERROR && _sql->NumRows() != 0 && _sql->NextRow() == SQL_SUCCESS) { - traverserEpoch = _sql->GetUIntData(0); + traverserEpoch = earth_time::time_point(std::chrono::seconds(_sql->GetUIntData(0))); traverserClaimed = _sql->GetUIntData(1); } - if (traverserEpoch == 0) + if (traverserEpoch == earth_time::time_point::min()) { // Players cannot accrue Traverser Stones until the epoch has been set. This is not possible // in quests, but is always displayed in player currencies. @@ -6977,16 +6986,18 @@ namespace charutils } // Handle reduction for Celerity Key Items - uint8 stoneWaitHours = 20; + earth_time::duration stoneWaitHours = 20h; for (int keyItem = 1385; keyItem <= 1387; ++keyItem) { if (hasKeyItem(PChar, keyItem)) { - stoneWaitHours -= 4; + stoneWaitHours -= 4h; } } + earth_time::duration elapsedSinceEpoch = earth_time::now() - traverserEpoch; + uint32 stonesGenerated = std::chrono::floor(elapsedSinceEpoch) / stoneWaitHours; - return floor((std::time(nullptr) - traverserEpoch) / (stoneWaitHours * 3600)) - traverserClaimed; + return stonesGenerated - traverserClaimed; } void ReadHistory(CCharEntity* PChar) @@ -7367,11 +7378,11 @@ namespace charutils if (rset && rset->rowsCount() && rset->next()) { // Update the character's death timestamp based off of how long they were previously dead - const auto secondsSinceDeath = rset->get("death"); + const auto secondsSinceDeath = std::chrono::seconds(rset->get("death")); if (PChar->health.hp == 0) { - PChar->SetDeathTimestamp((uint32)time(nullptr) - secondsSinceDeath); - PChar->Die(CCharEntity::death_duration - std::chrono::seconds(secondsSinceDeath)); + PChar->SetDeathTime(timer::time_point(timer::now() - secondsSinceDeath)); + PChar->Die(CCharEntity::death_duration - secondsSinceDeath); } } } diff --git a/src/map/utils/charutils.h b/src/map/utils/charutils.h index cd37a66eff0..152ff0e0d48 100644 --- a/src/map/utils/charutils.h +++ b/src/map/utils/charutils.h @@ -259,15 +259,15 @@ namespace charutils uint16 getWideScanRange(CCharEntity* PChar); void SendTimerPacket(CCharEntity* PChar, uint32 seconds); - void SendTimerPacket(CCharEntity* PChar, duration dur); + void SendTimerPacket(CCharEntity* PChar, timer::duration dur); void SendClearTimerPacket(CCharEntity* PChar); - time_t getTraverserEpoch(CCharEntity* PChar); - void setTraverserEpoch(CCharEntity* PChar); - uint32 getClaimedTraverserStones(CCharEntity* PChar); - void addClaimedTraverserStones(CCharEntity* PChar, uint16 numStones); - void setClaimedTraverserStones(CCharEntity* PChar, uint16 stoneTotal); - uint32 getAvailableTraverserStones(CCharEntity* PChar); + earth_time::time_point getTraverserEpoch(CCharEntity* PChar); + void setTraverserEpoch(CCharEntity* PChar); + uint32 getClaimedTraverserStones(CCharEntity* PChar); + void addClaimedTraverserStones(CCharEntity* PChar, uint16 numStones); + void setClaimedTraverserStones(CCharEntity* PChar, uint16 stoneTotal); + uint32 getAvailableTraverserStones(CCharEntity* PChar); void ReadHistory(CCharEntity* PChar); void WriteHistory(CCharEntity* PChar); diff --git a/src/map/utils/dboxutils.cpp b/src/map/utils/dboxutils.cpp index d60eb7b2635..67a9911117c 100644 --- a/src/map/utils/dboxutils.cpp +++ b/src/map/utils/dboxutils.cpp @@ -527,7 +527,7 @@ void dboxutils::SendNewItems(CCharEntity* PChar, uint8 action, uint8 boxtype, ui sender_name = PItem->getSender(), receiver = PChar->id, receiver_name = PChar->getName(), - date = static_cast(time(nullptr))]() + date = earth_time::timestamp()]() { const auto query = "INSERT INTO audit_dbox(itemid, quantity, sender, sender_name, receiver, receiver_name, date) VALUES (?, ?, ?, ?, ?, ?, ?)"; if (!db::preparedStmt(query, itemid, quantity, sender, sender_name, receiver, receiver_name, date)) diff --git a/src/map/utils/fishingutils.cpp b/src/map/utils/fishingutils.cpp index 52781538199..fdaf921af88 100644 --- a/src/map/utils/fishingutils.cpp +++ b/src/map/utils/fishingutils.cpp @@ -24,6 +24,7 @@ #include "common/database.h" #include "common/logging.h" #include "common/sql.h" +#include "common/timer.h" #include "common/utils.h" #include "common/vana_time.h" @@ -156,20 +157,12 @@ namespace fishingutils * CALCULATIONS * * * ************************************************************************/ - uint32 GetSundayMidnightTimestamp() - { - uint32 timestamp = (uint32)time(nullptr); - uint32 day = 6 - CVanaTime::getInstance()->getSysWeekDay(); - uint32 hour = 23 - CVanaTime::getInstance()->getSysHour(); - uint32 mins = 59 - CVanaTime::getInstance()->getSysMinute(); - uint32 secs = 59 - CVanaTime::getInstance()->getSysSecond(); - return timestamp + secs + (mins * 60) + (hour * 3600) + (day * 86400) + 1; - } uint8 GetMoonPhase() { - uint8 phase = (uint8)CVanaTime::getInstance()->getMoonPhase(); - uint8 direction = CVanaTime::getInstance()->getMoonDirection(); + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + uint8 phase = static_cast(vanadiel_time::moon::get_phase(vanaTime)); + uint8 direction = vanadiel_time::moon::get_direction(vanaTime); if (phase <= 5 || (phase <= 10 && direction == 1)) // New Moon { @@ -210,7 +203,7 @@ namespace fishingutils { uint8 waitTime = 13; uint8 moonPhase = GetMoonPhase(); - uint8 hour = (uint8)CVanaTime::getInstance()->getHour(); + uint8 hour = static_cast(vanadiel_time::get_hour()); fishing_gear_t gear = GetFishingGear(PChar); if (moonPhase == MOONPHASE_NEW || moonPhase == MOONPHASE_FULL) @@ -234,7 +227,7 @@ namespace fishingutils float GetMonthlyTidalInfluence(fish_t* fish) // 0.25 to 1.25 { float modifier = 0.5f; - uint8 month = (uint8)CVanaTime::getInstance()->getMonth(); + uint8 month = static_cast(vanadiel_time::get_month() - 1); switch (fish->monthPattern) { @@ -276,7 +269,7 @@ namespace fishingutils float GetHourlyModifier(fish_t* fish) { // 0.25 to 1.25 float modifier = 0.5f; - uint8 hour = (uint8)CVanaTime::getInstance()->getHour(); + uint8 hour = static_cast(vanadiel_time::get_hour()); switch (fish->hourPattern) { @@ -531,7 +524,7 @@ namespace fishingutils bonus += (moonModifier * 5) + (moonModifier * xirand::GetRandomNumber(1, 5)); // Time of Day modifier - uint32 gameHour = CVanaTime::getInstance()->getHour(); + uint32 gameHour = vanadiel_time::get_hour(); if ((gameHour == 6 || gameHour == 7) || (gameHour >= 16 && gameHour <= 18)) { @@ -1622,7 +1615,7 @@ namespace fishingutils PMob->Spawn(); PMob->setMobMod(MOBMOD_CHARMABLE, 0); PMob->setMobMod(MOBMOD_IDLE_DESPAWN, 180); - PMob->SetDespawnTime(std::chrono::seconds(180)); + PMob->SetDespawnTime(180s); PMob->SetLocalVar("hooked", 0); if (mob->maxRespawn > mob->minRespawn) @@ -1817,9 +1810,12 @@ namespace fishingutils // Configuration multiplier. maxChance = maxChance * settings::get("map.FISHING_SKILL_MULTIPLIER"); + vanadiel_time::time_point vanaTime = vanadiel_time::now(); + // Moon phase skillup modifiers - uint8 phase = CVanaTime::getInstance()->getMoonPhase(); - uint8 moonDirection = CVanaTime::getInstance()->getMoonDirection(); + uint8 phase = static_cast(vanadiel_time::moon::get_phase(vanaTime)); + uint8 moonDirection = vanadiel_time::moon::get_direction(vanaTime); + switch (moonDirection) { case 0: // None @@ -1942,6 +1938,8 @@ namespace fishingutils void StartFishing(CCharEntity* PChar) { + auto currentTime = earth_time::now(); + if (!settings::get("map.FISHING_ENABLE")) { ShowWarning("Fishing is currently disabled"); @@ -1964,7 +1962,7 @@ namespace fishingutils CItemWeapon* Rod = nullptr; CItemWeapon* Bait = nullptr; uint8 FishingAreaID = 0; - uint32 vanaTime = CVanaTime::getInstance()->getVanaTime(); + uint32 vanaTime = earth_time::vanadiel_timestamp(currentTime); if (PChar->nextFishTime > vanaTime) { @@ -1974,8 +1972,7 @@ namespace fishingutils } else { - auto secs = std::chrono::duration_cast(server_clock::now().time_since_epoch()); - PChar->setCharVar("[Fish]LastCastTime", secs.count()); + PChar->setCharVar("[Fish]LastCastTime", earth_time::timestamp(currentTime)); PChar->lastCastTime = vanaTime; PChar->nextFishTime = PChar->lastCastTime + 5; } @@ -2099,7 +2096,7 @@ namespace fishingutils if (lost && PChar->hookedFish->nm && PChar->hookedFish->nmFlags & FISHINGNM_RESET_RESPAWN_ON_FAIL) { - PMob->SetLocalVar("lastTOD", (uint32)time(nullptr)); + PMob->SetLocalVar("lastTOD", earth_time::timestamp()); } } } @@ -2309,7 +2306,7 @@ namespace fishingutils else if (mob->maxRespawn > 0) { uint32 respawnTime = PMob->GetLocalVar("lastTOD") + PMob->GetLocalVar("respawnTime"); - if ((uint32)time(nullptr) > respawnTime) + if (earth_time::timestamp() > respawnTime) { mobAdd = true; MobPoolWeight += 50; @@ -2569,7 +2566,7 @@ namespace fishingutils if (PMob != nullptr && PMob->GetLocalVar("hooked") == 0) { PMob->SetLocalVar("hooked", 1); - PMob->SetLocalVar("hookedTime", (uint32)time(nullptr)); + PMob->SetLocalVar("hookedTime", earth_time::timestamp()); response->hooked = true; response->catchid = MobSelection->mobId; @@ -2680,7 +2677,7 @@ namespace fishingutils } uint16 MessageOffset = GetMessageOffset(PChar->getZone()); - uint32 vanaTime = CVanaTime::getInstance()->getVanaTime(); + uint32 vanaTime = earth_time::vanadiel_timestamp(); switch (action) { diff --git a/src/map/utils/fishingutils.h b/src/map/utils/fishingutils.h index 087c89ada7f..7aef377b6ef 100644 --- a/src/map/utils/fishingutils.h +++ b/src/map/utils/fishingutils.h @@ -931,7 +931,6 @@ namespace fishingutils uint32 HandleFishingAction(CCharEntity* PChar, CBasicPacket& data); // Calculations - uint32 GetSundayMidnightTimestamp(); uint8 GetMoonPhase(); uint8 GetHookTime(CCharEntity* PChar); float GetMonthlyTidalInfluence(fish_t* fish); diff --git a/src/map/utils/gardenutils.cpp b/src/map/utils/gardenutils.cpp index 874edf0139f..c26b27dd4b4 100644 --- a/src/map/utils/gardenutils.cpp +++ b/src/map/utils/gardenutils.cpp @@ -87,7 +87,7 @@ namespace gardenutils void UpdateGardening(CCharEntity* PChar, bool sendPacket) { TracyZoneScoped; - uint32 vanatime = CVanaTime::getInstance()->getVanaTime(); + uint32 vanatime = earth_time::vanadiel_timestamp(); for (auto containerID : { LOC_MOGSAFE, LOC_MOGSAFE2 }) { CItemContainer* PContainer = PChar->getStorage(containerID); @@ -170,8 +170,9 @@ namespace gardenutils if (settings::get("map.GARDEN_DAY_MATTERS")) { - uint32 vanaDate = PItem->getPlantTimestamp(); - uint32 dayElement = ((vanaDate % VTIME_WEEK) / VTIME_DAY) + 1; + earth_time::duration vanaTimestamp = std::chrono::seconds(PItem->getPlantTimestamp()); + vanadiel_time::time_point vanaDate = vanadiel_time::time_point(std::chrono::duration_cast(vanaTimestamp)); + uint32 dayElement = vanadiel_time::get_weekday(vanaDate) + 1; elements[dayElement] += 10; } @@ -239,7 +240,7 @@ namespace gardenutils if (settings::get("map.GARDEN_MOONPHASE_MATTERS")) { - strength += (int16)std::ceil(CVanaTime::getInstance()->getMoonPhase() / 10.0f); + strength += static_cast(std::ceil(vanadiel_time::moon::get_phase() / 10.0f)); } if (settings::get("map.GARDEN_MH_AURA_MATTERS")) @@ -357,7 +358,8 @@ namespace gardenutils break; } - PItem->setStageTimestamp(CVanaTime::getInstance()->getVanaTime() + GetStageDuration(PItem, growFromFeed) * VANADAY_SECONDS); + vanadiel_time::time_point stageTimestamp = vanadiel_time::now() + xi::vanadiel_clock::days(GetStageDuration(PItem, growFromFeed)); + PItem->setStageTimestamp(earth_time::vanadiel_timestamp(vanadiel_time::to_earth_time(stageTimestamp))); } uint8 GetStageDuration(CItemFlowerpot* PItem, bool growFromFeed /*= false*/) diff --git a/src/map/utils/guildutils.cpp b/src/map/utils/guildutils.cpp index 128e31cb89d..798377cc1c5 100644 --- a/src/map/utils/guildutils.cpp +++ b/src/map/utils/guildutils.cpp @@ -157,14 +157,14 @@ namespace guildutils void UpdateGuildPointsPattern() { // TODO: This function can be faulty when dealing with multiple processes. Needs to be synchronized properly across servers. - - bool doUpdate = static_cast(serverutils::GetServerVar("[GUILD]pattern_update")) != CVanaTime::getInstance()->getJstYearDay(); + auto jstDayOfYear = earth_time::jst::get_yearday(); + bool doUpdate = static_cast(serverutils::GetServerVar("[GUILD]pattern_update")) != jstDayOfYear; uint8 pattern = xirand::GetRandomNumber(8); if (doUpdate) { // write the new pattern and update time to try to prevent other servers from updating the pattern - serverutils::SetServerVar("[GUILD]pattern_update", CVanaTime::getInstance()->getJstYearDay()); + serverutils::SetServerVar("[GUILD]pattern_update", jstDayOfYear); serverutils::SetServerVar("[GUILD]pattern", pattern); charutils::ClearCharVarFromAll("[GUILD]daily_points"); } diff --git a/src/map/utils/itemutils.cpp b/src/map/utils/itemutils.cpp index 230c95e1e5b..9d39fd87e07 100644 --- a/src/map/utils/itemutils.cpp +++ b/src/map/utils/itemutils.cpp @@ -426,13 +426,13 @@ namespace itemutils if (PItem->isType(ITEM_USABLE)) { ((CItemUsable*)PItem)->setValidTarget(_sql->GetUIntData(7)); - ((CItemUsable*)PItem)->setActivationTime(_sql->GetUIntData(8) * 1000); + ((CItemUsable*)PItem)->setActivationTime(std::chrono::seconds(_sql->GetUIntData(8))); ((CItemUsable*)PItem)->setAnimationID(_sql->GetUIntData(9)); - ((CItemUsable*)PItem)->setAnimationTime(_sql->GetUIntData(10) * 1000); + ((CItemUsable*)PItem)->setAnimationTime(std::chrono::seconds(_sql->GetUIntData(10))); ((CItemUsable*)PItem)->setMaxCharges(_sql->GetUIntData(11)); ((CItemUsable*)PItem)->setCurrentCharges(_sql->GetUIntData(11)); - ((CItemUsable*)PItem)->setUseDelay(_sql->GetUIntData(12)); - ((CItemUsable*)PItem)->setReuseDelay(_sql->GetUIntData(13)); + ((CItemUsable*)PItem)->setUseDelay(std::chrono::seconds(_sql->GetUIntData(12))); + ((CItemUsable*)PItem)->setReuseDelay(std::chrono::seconds(_sql->GetUIntData(13))); ((CItemUsable*)PItem)->setAoE(_sql->GetUIntData(14)); } if (PItem->isType(ITEM_PUPPET)) diff --git a/src/map/utils/mobutils.cpp b/src/map/utils/mobutils.cpp index c4d395cdf02..1b3159418cf 100644 --- a/src/map/utils/mobutils.cpp +++ b/src/map/utils/mobutils.cpp @@ -1580,7 +1580,7 @@ namespace mobutils PMob->name.insert(0, (const char*)_sql->GetData(1)); PMob->packetName.insert(0, (const char*)_sql->GetData(2)); - PMob->m_RespawnTime = _sql->GetUIntData(3) * 1000; + PMob->m_RespawnTime = std::chrono::seconds(_sql->GetUIntData(3)); PMob->m_SpawnType = (SPAWNTYPE)_sql->GetUIntData(4); PMob->m_DropID = _sql->GetUIntData(5); @@ -1738,7 +1738,7 @@ namespace mobutils PMob->name.insert(0, (const char*)_sql->GetData(1)); PMob->packetName.insert(0, (const char*)_sql->GetData(2)); - PMob->m_RespawnTime = _sql->GetUIntData(3) * 1000; + PMob->m_RespawnTime = std::chrono::seconds(_sql->GetUIntData(3)); PMob->m_SpawnType = (SPAWNTYPE)_sql->GetUIntData(4); PMob->m_DropID = _sql->GetUIntData(5); diff --git a/src/map/utils/petutils.cpp b/src/map/utils/petutils.cpp index 0ac78bd0b72..530c01fff7c 100644 --- a/src/map/utils/petutils.cpp +++ b/src/map/utils/petutils.cpp @@ -116,7 +116,7 @@ namespace petutils Pet->minLevel = (uint8)_sql->GetIntData(3); Pet->maxLevel = (uint8)_sql->GetIntData(4); - Pet->time = _sql->GetUIntData(5); + Pet->time = std::chrono::seconds(_sql->GetUIntData(5)); Pet->radius = _sql->GetUIntData(6); Pet->EcoSystem = (ECOSYSTEM)_sql->GetIntData(7); Pet->m_Family = (uint16)_sql->GetIntData(8); @@ -1167,15 +1167,15 @@ namespace petutils if (PMaster->StatusEffectContainer->HasStatusEffect(EFFECT_DEBILITATION)) { - PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DEBILITATION, EFFECT_DEBILITATION, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_DEBILITATION)->GetPower(), 0, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_DEBILITATION)->GetDuration()), EffectNotice::Silent); + PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_DEBILITATION, EFFECT_DEBILITATION, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_DEBILITATION)->GetPower(), 0s, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_DEBILITATION)->GetDuration()), EffectNotice::Silent); } if (PMaster->StatusEffectContainer->HasStatusEffect(EFFECT_OMERTA)) { - PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_OMERTA, EFFECT_OMERTA, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_OMERTA)->GetPower(), 0, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_OMERTA)->GetDuration()), EffectNotice::Silent); + PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_OMERTA, EFFECT_OMERTA, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_OMERTA)->GetPower(), 0s, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_OMERTA)->GetDuration()), EffectNotice::Silent); } if (PMaster->StatusEffectContainer->HasStatusEffect(EFFECT_IMPAIRMENT)) { - PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_IMPAIRMENT, EFFECT_IMPAIRMENT, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_IMPAIRMENT)->GetPower(), 0, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_IMPAIRMENT)->GetDuration()), EffectNotice::Silent); + PPet->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_IMPAIRMENT, EFFECT_IMPAIRMENT, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_IMPAIRMENT)->GetPower(), 0s, PMaster->StatusEffectContainer->GetStatusEffect(EFFECT_IMPAIRMENT)->GetDuration()), EffectNotice::Silent); } } @@ -1360,7 +1360,7 @@ namespace petutils PMob->isCharmed = false; PMob->allegiance = ALLEGIANCE_TYPE::MOB; - PMob->charmTime = time_point::min(); + PMob->charmTime = timer::time_point::min(); PMob->PMaster = nullptr; PMob->PAI->SetController(std::make_unique(PMob)); diff --git a/src/map/utils/petutils.h b/src/map/utils/petutils.h index 8ee4364bb91..528f26db056 100644 --- a/src/map/utils/petutils.h +++ b/src/map/utils/petutils.h @@ -71,10 +71,10 @@ struct Pet_t uint8 minLevel; uint8 maxLevel; - uint8 name_prefix; - uint8 radius; // Model Radius - affects melee range etc. - uint16 m_Family; - uint32 time; // Duration of pet's "life span" before despawning + uint8 name_prefix; + uint8 radius; // Model Radius - affects melee range etc. + uint16 m_Family; + timer::duration time; // Duration of pet's "life span" before despawning uint8 mJob; uint8 sJob; @@ -138,7 +138,7 @@ struct Pet_t , name_prefix(0) , radius(0) , m_Family(0) - , time(0) + , time(0s) , mJob(0) , sJob(0) , m_Element(0) diff --git a/src/map/utils/serverutils.cpp b/src/map/utils/serverutils.cpp index c3d5456dc59..c43a4d48b02 100644 --- a/src/map/utils/serverutils.cpp +++ b/src/map/utils/serverutils.cpp @@ -47,9 +47,7 @@ namespace serverutils value = rset->get("value"); expiry = rset->get("expiry"); - uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); - - if (expiry > 0 && expiry <= currentTimestamp) + if (expiry > 0 && expiry <= earth_time::timestamp()) { value = 0; db::preparedStmt("DELETE FROM server_variables WHERE name = ? LIMIT 1", name); @@ -75,12 +73,11 @@ namespace serverutils { if (auto var = serverVarCache.find(name); var != serverVarCache.end()) { - std::pair cachedVarData = var->second; - uint32 currentTimestamp = CVanaTime::getInstance()->getSysTime(); + std::pair cachedVarData = var->second; // If the cached variable is not expired, return it. Else, fall through so that the // database can be cleaned up. - if (cachedVarData.second == 0 || cachedVarData.second > currentTimestamp) + if (cachedVarData.second == 0 || cachedVarData.second > earth_time::timestamp()) { return cachedVarData.first; } @@ -89,7 +86,7 @@ namespace serverutils return GetServerVar(name); } - int32 PersistVolatileServerVars(time_point tick, CTaskManager::CTask* PTask) + int32 PersistVolatileServerVars(timer::time_point tick, CTaskManager::CTask* PTask) { if (serverVarChanges.empty()) { diff --git a/src/map/utils/serverutils.h b/src/map/utils/serverutils.h index 4e4d7ff1f18..e55d5297e79 100644 --- a/src/map/utils/serverutils.h +++ b/src/map/utils/serverutils.h @@ -37,7 +37,7 @@ namespace serverutils int32 GetVolatileServerVar(std::string const& var); void SetVolatileServerVar(std::string const& var, int32 value, uint32 expiry = 0); - int32 PersistVolatileServerVars(time_point tick, CTaskManager::CTask* PTask); + int32 PersistVolatileServerVars(timer::time_point tick, CTaskManager::CTask* PTask); } // namespace serverutils #endif // _SERVERUTILS_H diff --git a/src/map/utils/synthutils.cpp b/src/map/utils/synthutils.cpp index 7985c1e62ce..5af6758c859 100644 --- a/src/map/utils/synthutils.cpp +++ b/src/map/utils/synthutils.cpp @@ -23,6 +23,7 @@ #include "common/database.h" #include "common/logging.h" +#include "common/timer.h" #include "common/utils.h" #include "common/vana_time.h" @@ -1062,7 +1063,7 @@ namespace synthutils int32 startSynth(CCharEntity* PChar) { - PChar->m_LastSynthTime = server_clock::now(); + PChar->m_LastSynthTime = timer::now(); if (!isRightRecipe(PChar)) { diff --git a/src/map/utils/zoneutils.cpp b/src/map/utils/zoneutils.cpp index d2fbd64be5d..fa3c83fa039 100644 --- a/src/map/utils/zoneutils.cpp +++ b/src/map/utils/zoneutils.cpp @@ -55,7 +55,7 @@ namespace zoneutils * * ************************************************************************/ - void TOTDChange(TIMETYPE TOTD) + void TOTDChange(vanadiel_time::TOTD TOTD) { for (auto PZone : g_PZoneList) { @@ -455,7 +455,7 @@ namespace zoneutils PMob->m_SpawnPoint.z = rset->get("pos_z"); PMob->loc.p = PMob->m_SpawnPoint; - PMob->m_RespawnTime = rset->get("respawntime") * 1000; + PMob->m_RespawnTime = std::chrono::seconds(rset->get("respawntime")); PMob->m_SpawnType = static_cast(rset->get("spawntype")); PMob->m_DropID = rset->get("dropid"); @@ -680,9 +680,9 @@ namespace zoneutils } else { - PMob->PAI->Internal_Respawn(std::chrono::milliseconds(PMob->m_RespawnTime)); + PMob->PAI->Internal_Respawn(PMob->m_RespawnTime); // If the mob is a scripted spawn and it has a respawn time defined when the mob initializes then allow it to respawn - if (PMob->m_SpawnType == SPAWNTYPE_SCRIPTED && PMob->m_RespawnTime > 0) + if (PMob->m_SpawnType == SPAWNTYPE_SCRIPTED && PMob->m_RespawnTime > 0s) { PMob->m_AllowRespawn = true; } diff --git a/src/map/utils/zoneutils.h b/src/map/utils/zoneutils.h index ab7e7845d67..6bb5ff3d701 100644 --- a/src/map/utils/zoneutils.h +++ b/src/map/utils/zoneutils.h @@ -36,7 +36,7 @@ namespace zoneutils void LoadZoneList(IPP mapIPP); void FreeZoneList(); void InitializeWeather(); - void TOTDChange(TIMETYPE TOTD); + void TOTDChange(vanadiel_time::TOTD TOTD); void SavePlayTime(); REGION_TYPE GetCurrentRegion(uint16 ZoneID); diff --git a/src/map/weapon_skill.cpp b/src/map/weapon_skill.cpp index 3c401c0ad79..cb4e60c6387 100644 --- a/src/map/weapon_skill.cpp +++ b/src/map/weapon_skill.cpp @@ -114,7 +114,7 @@ void CWeaponSkill::setAnimationId(int8 id) m_AnimationId = id; } -void CWeaponSkill::setAnimationTime(duration time) +void CWeaponSkill::setAnimationTime(timer::duration time) { m_AnimationTime = time; } @@ -169,7 +169,7 @@ uint8 CWeaponSkill::getAnimationId() const return m_AnimationId; } -duration CWeaponSkill::getAnimationTime() +timer::duration CWeaponSkill::getAnimationTime() { return m_AnimationTime; } diff --git a/src/map/weapon_skill.h b/src/map/weapon_skill.h index 36a72a3dcbb..f809b9e80cb 100644 --- a/src/map/weapon_skill.h +++ b/src/map/weapon_skill.h @@ -41,13 +41,13 @@ class CWeaponSkill uint8 getElement() const; bool isElemental() const; - bool isAoE() const; - bool mainOnly() const; // can only be used as main job - uint8 getAoe() const; - uint8 getAnimationId() const; - duration getAnimationTime(); - uint8 getType() const; - uint8 getUnlockId() const; + bool isAoE() const; + bool mainOnly() const; // can only be used as main job + uint8 getAoe() const; + uint8 getAnimationId() const; + timer::duration getAnimationTime(); + uint8 getType() const; + uint8 getUnlockId() const; void setID(uint16 id); void setJob(int8* jobs); @@ -59,7 +59,7 @@ class CWeaponSkill void setTertiarySkillchain(uint8 skillchain); void setAoe(uint8 aoe); void setAnimationId(int8 animation); - void setAnimationTime(duration time); + void setAnimationTime(timer::duration time); void setType(uint8 type); void setMainOnly(uint8 main); void setUnlockId(uint8 id); @@ -72,20 +72,20 @@ class CWeaponSkill void setName(const std::string& name); private: - uint16 m_ID; - uint8 m_TypeID; - uint8 m_Job[MAX_JOBTYPE]{}; - uint16 m_Skilllevel; - uint8 m_AnimationId; - duration m_AnimationTime{}; - uint8 m_Element; - uint8 m_PrimarySkillchain; - uint8 m_SecondarySkillchain; - uint8 m_TertiarySkillchain; - uint8 m_Range; - uint8 m_AOE; - uint8 m_mainOnly; - uint8 m_unlockId; + uint16 m_ID; + uint8 m_TypeID; + uint8 m_Job[MAX_JOBTYPE]{}; + uint16 m_Skilllevel; + uint8 m_AnimationId; + timer::duration m_AnimationTime{}; + uint8 m_Element; + uint8 m_PrimarySkillchain; + uint8 m_SecondarySkillchain; + uint8 m_TertiarySkillchain; + uint8 m_Range; + uint8 m_AOE; + uint8 m_mainOnly; + uint8 m_unlockId; std::string m_name; }; diff --git a/src/map/zone.cpp b/src/map/zone.cpp index 528d0732f65..6265022df9b 100644 --- a/src/map/zone.cpp +++ b/src/map/zone.cpp @@ -547,7 +547,7 @@ void CZone::updateCharLevelRestriction(CCharEntity* PChar) PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_ROLL, EffectNotice::Silent); PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_SYNTH_SUPPORT, EffectNotice::Silent); PChar->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_BLOODPACT, EffectNotice::Silent); - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, m_levelRestriction, 0, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, m_levelRestriction, 0s, 0s)); } } @@ -569,7 +569,7 @@ void CZone::SetWeather(WEATHER weather) m_zoneEntities->WeatherChange(weather); m_Weather = weather; - m_WeatherChangeTime = CVanaTime::getInstance()->getVanaTime(); + m_WeatherChangeTime = earth_time::vanadiel_timestamp(); m_zoneEntities->PushPacket(nullptr, CHAR_INZONE, std::make_unique(m_WeatherChangeTime, m_Weather, xirand::GetRandomNumber(4, 28))); } @@ -578,22 +578,19 @@ void CZone::UpdateWeather() { TracyZoneScoped; - uint32 CurrentVanaDate = CVanaTime::getInstance()->getDate(); // Current Vanadiel timestamp in minutes - uint32 StartFogVanaDate = (CurrentVanaDate - (CurrentVanaDate % VTIME_DAY)) + (VTIME_HOUR * 2); // Vanadiel timestamp of 2 AM in minutes - uint32 EndFogVanaDate = StartFogVanaDate + (VTIME_HOUR * 5); // Vanadiel timestamp of 7 AM in minutes - uint32 WeatherNextUpdate = 0; - uint32 WeatherDay = 0; - uint8 WeatherChance = 0; + vanadiel_time::time_point CurrentVanaDate = vanadiel_time::now(); // Current Vanadiel time + vanadiel_time::time_point nextVanaMidnight = vanadiel_time::get_next_midnight(CurrentVanaDate); + vanadiel_time::time_point StartFogVanaDate = nextVanaMidnight - xi::vanadiel_clock::days(1) + xi::vanadiel_clock::hours(2); // Vanadiel timestamp of 2 AM in minutes + vanadiel_time::time_point EndFogVanaDate = StartFogVanaDate + xi::vanadiel_clock::hours(5); // Vanadiel timestamp of 7 AM in minutes + vanadiel_time::duration WeatherNextUpdate = 0s; + uint32 WeatherDay = 0; + uint8 WeatherChance = 0; // Random time between 3 minutes and 30 minutes for the next weather change - WeatherNextUpdate = (xirand::GetRandomNumber(180, 1801)); - - // Find the timestamp since the start of vanadiel - WeatherDay = CVanaTime::getInstance()->getVanaTime(); + WeatherNextUpdate = xi::vanadiel_clock::seconds(xirand::GetRandomNumber(180, 1801)); // Calculate what day we are on since the start of vanadiel time - // 1 Vana'diel Day = 57 minutes 36 seconds or 3456 seconds - WeatherDay = WeatherDay / 3456; + WeatherDay = vanadiel_time::count_days(CurrentVanaDate.time_since_epoch()); // The weather starts over again every 2160 days WeatherDay = WeatherDay % WEATHER_CYCLE; @@ -638,16 +635,16 @@ void CZone::UpdateWeather() { Weather = WEATHER_FOG; // Force the weather to change by 7 am - // 2.4 vanadiel minutes = 1 earth second - WeatherNextUpdate = (uint32)((EndFogVanaDate - CurrentVanaDate) * 2.4); + WeatherNextUpdate = EndFogVanaDate - CurrentVanaDate; } SetWeather((WEATHER)Weather); luautils::OnZoneWeatherChange(GetID(), Weather); // clang-format off - CTaskManager::getInstance()->AddTask("zone_update_weather", server_clock::now() + std::chrono::seconds(WeatherNextUpdate), this, CTaskManager::TASK_ONCE, 1s, - [](time_point tick, CTaskManager::CTask* PTask) + timer::time_point nextWeatherTick = timer::now() + std::chrono::duration_cast(WeatherNextUpdate); + CTaskManager::getInstance()->AddTask("zone_update_weather", nextWeatherTick, this, CTaskManager::TASK_ONCE, 1s, + [](timer::time_point tick, CTaskManager::CTask* PTask) { CZone* PZone = std::any_cast(PTask->m_data); if (!PZone->IsWeatherStatic()) @@ -696,7 +693,7 @@ void CZone::DecreaseZoneCounter(CCharEntity* PChar) if (m_zoneEntities->CharListEmpty()) { - m_timeZoneEmpty = server_clock::now(); + m_timeZoneEmpty = timer::now(); } else { @@ -790,7 +787,7 @@ CBaseEntity* CZone::GetEntity(uint16 targid, uint8 filter) * * ************************************************************************/ -void CZone::TOTDChange(TIMETYPE TOTD) +void CZone::TOTDChange(vanadiel_time::TOTD TOTD) { TracyZoneScoped; @@ -844,7 +841,7 @@ void CZone::WideScan(CCharEntity* PChar, uint16 radius) * * ************************************************************************/ -void CZone::ZoneServer(time_point tick) +void CZone::ZoneServer(timer::time_point tick) { TracyZoneScoped; @@ -855,7 +852,7 @@ void CZone::ZoneServer(time_point tick) m_BattlefieldHandler->HandleBattlefields(tick); } - if (ZoneTimer && m_zoneEntities->CharListEmpty() && m_timeZoneEmpty + 5s < server_clock::now() && CheckMobsPathedBack()) + if (ZoneTimer && m_zoneEntities->CharListEmpty() && m_timeZoneEmpty + 5s < timer::now() && CheckMobsPathedBack()) { ZoneTimer->m_type = CTaskManager::TASK_REMOVE; ZoneTimer = nullptr; @@ -954,16 +951,16 @@ void CZone::createZoneTimers() TracyZoneScoped; // clang-format off - ZoneTimer = CTaskManager::getInstance()->AddTask(m_zoneName, server_clock::now(), this, CTaskManager::TASK_INTERVAL, kLogicUpdateInterval, - [](time_point tick, CTaskManager::CTask* PTask) + ZoneTimer = CTaskManager::getInstance()->AddTask(m_zoneName, timer::now(), this, CTaskManager::TASK_INTERVAL, kLogicUpdateInterval, + [](timer::time_point tick, CTaskManager::CTask* PTask) { CZone* PZone = std::any_cast(PTask->m_data); PZone->ZoneServer(tick); return 0; }); - ZoneTimerTriggerAreas = CTaskManager::getInstance()->AddTask(m_zoneName + "TriggerAreas", server_clock::now(), this, CTaskManager::TASK_INTERVAL, kTriggerAreaInterval, - [](time_point tick, CTaskManager::CTask* PTask) + ZoneTimerTriggerAreas = CTaskManager::getInstance()->AddTask(m_zoneName + "TriggerAreas", timer::now(), this, CTaskManager::TASK_INTERVAL, kTriggerAreaInterval, + [](timer::time_point tick, CTaskManager::CTask* PTask) { CZone* PZone = std::any_cast(PTask->m_data); PZone->CheckTriggerAreas(); diff --git a/src/map/zone.h b/src/map/zone.h index 69fb32c077a..f19ae787bde 100644 --- a/src/map/zone.h +++ b/src/map/zone.h @@ -25,6 +25,7 @@ #include "common/cbasetypes.h" #include "common/mmo.h" #include "common/task_manager.h" +#include "common/timer.h" #include "common/vana_time.h" #include @@ -615,7 +616,7 @@ class CZone void InsertTriggerArea(std::unique_ptr&& triggerArea); // Add an active area to the zone - virtual void TOTDChange(TIMETYPE TOTD); + virtual void TOTDChange(vanadiel_time::TOTD TOTD); virtual void PushPacket(CBaseEntity*, GLOBAL_MESSAGE_TYPE, const std::unique_ptr&); virtual void UpdateEntityPacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask, bool alwaysInclude = false); @@ -625,7 +626,7 @@ class CZone weatherVector_t m_WeatherVector; // The probability of each weather type - virtual void ZoneServer(time_point tick); + virtual void ZoneServer(timer::time_point tick); virtual void CheckTriggerAreas(); virtual void ForEachChar(std::function const& func); @@ -650,7 +651,7 @@ class CZone std::unique_ptr m_navMesh; std::unique_ptr lineOfSight; - time_point m_LoadedAt; // The time the zone was loaded + timer::time_point m_LoadedAt; // The time the zone was loaded void LoadNavMesh(); void LoadZoneLos(); @@ -686,7 +687,7 @@ class CZone CTreasurePool* m_TreasurePool; - time_point m_timeZoneEmpty; // The time point when the last player left the zone + timer::time_point m_timeZoneEmpty; // The time point when the last player left the zone std::unordered_map m_queryByNameResults; diff --git a/src/map/zone_entities.cpp b/src/map/zone_entities.cpp index 30d8008c68c..34c75c15e2c 100644 --- a/src/map/zone_entities.cpp +++ b/src/map/zone_entities.cpp @@ -670,7 +670,7 @@ void CZoneEntities::EraseStaleDynamicTargIDs() for (auto it = m_dynamicTargIdsToDelete.begin(); it != m_dynamicTargIdsToDelete.end();) { // Erase dynamic targid if it's stale enough - if ((server_clock::now() - it->second) > 60s) + if ((timer::now() - it->second) > 60s) { m_dynamicTargIds.erase(it->first); it = m_dynamicTargIdsToDelete.erase(it); @@ -1338,7 +1338,7 @@ CBaseEntity* CZoneEntities::GetEntity(uint16 targid, uint8 filter) return nullptr; } -void CZoneEntities::TOTDChange(TIMETYPE TOTD) +void CZoneEntities::TOTDChange(vanadiel_time::TOTD TOTD) { TracyZoneScoped; @@ -1346,11 +1346,11 @@ void CZoneEntities::TOTDChange(TIMETYPE TOTD) switch (TOTD) { - case TIME_MIDNIGHT: + case vanadiel_time::TOTD::MIDNIGHT: { } break; - case TIME_NEWDAY: + case vanadiel_time::TOTD::NEWDAY: { FOR_EACH_PAIR_CAST_SECOND(CMobEntity*, PMob, m_mobList) { @@ -1362,7 +1362,7 @@ void CZoneEntities::TOTDChange(TIMETYPE TOTD) } } break; - case TIME_DAWN: + case vanadiel_time::TOTD::DAWN: { ScriptType = SCRIPT_TIME_DAWN; @@ -1376,17 +1376,17 @@ void CZoneEntities::TOTDChange(TIMETYPE TOTD) } } break; - case TIME_DAY: + case vanadiel_time::TOTD::DAY: { ScriptType = SCRIPT_TIME_DAY; } break; - case TIME_DUSK: + case vanadiel_time::TOTD::DUSK: { ScriptType = SCRIPT_TIME_DUSK; } break; - case TIME_EVENING: + case vanadiel_time::TOTD::EVENING: { ScriptType = SCRIPT_TIME_EVENING; @@ -1401,7 +1401,7 @@ void CZoneEntities::TOTDChange(TIMETYPE TOTD) } } break; - case TIME_NIGHT: + case vanadiel_time::TOTD::NIGHT: { FOR_EACH_PAIR_CAST_SECOND(CMobEntity*, PMob, m_mobList) { @@ -1671,7 +1671,7 @@ void CZoneEntities::WideScan(CCharEntity* PChar, uint16 radius) PChar->pushPacket(WIDESCAN_END); } -void CZoneEntities::ZoneServer(time_point tick) +void CZoneEntities::ZoneServer(timer::time_point tick) { TracyZoneScoped; TracyZoneString(m_zone->getName()); @@ -1927,7 +1927,7 @@ void CZoneEntities::ZoneServer(time_point tick) if (auto itr = m_mobList.find(PMob->targid); itr != m_mobList.end()) { m_mobList.erase(itr); - m_dynamicTargIdsToDelete.emplace_back(PMob->targid, server_clock::now()); + m_dynamicTargIdsToDelete.emplace_back(PMob->targid, timer::now()); destroy(PMob); } } @@ -1937,7 +1937,7 @@ void CZoneEntities::ZoneServer(time_point tick) if (auto itr = m_npcList.find(PNpc->targid); itr != m_npcList.end()) { m_npcList.erase(itr); - m_dynamicTargIdsToDelete.emplace_back(PNpc->targid, server_clock::now()); + m_dynamicTargIdsToDelete.emplace_back(PNpc->targid, timer::now()); destroy(PNpc); } } @@ -1947,7 +1947,7 @@ void CZoneEntities::ZoneServer(time_point tick) if (auto itr = m_petList.find(PPet->targid); itr != m_petList.end()) { m_petList.erase(itr); - m_dynamicTargIdsToDelete.emplace_back(PPet->targid, server_clock::now()); + m_dynamicTargIdsToDelete.emplace_back(PPet->targid, timer::now()); destroy(PPet); } } @@ -1957,7 +1957,7 @@ void CZoneEntities::ZoneServer(time_point tick) if (auto itr = m_trustList.find(PTrust->targid); itr != m_trustList.end()) { m_trustList.erase(itr); - m_dynamicTargIdsToDelete.emplace_back(PTrust->targid, server_clock::now()); + m_dynamicTargIdsToDelete.emplace_back(PTrust->targid, timer::now()); destroy(PTrust); } } diff --git a/src/map/zone_entities.h b/src/map/zone_entities.h index a7a37917d71..b90b4d8c7fb 100644 --- a/src/map/zone_entities.h +++ b/src/map/zone_entities.h @@ -24,6 +24,8 @@ #include "zone.h" +#include "common/timer.h" + #include "entities/baseentity.h" #include "entities/charentity.h" #include "entities/mobentity.h" @@ -73,13 +75,13 @@ class CZoneEntities void FindPartyForMob(CBaseEntity* PEntity); // looking for a party for the monster void TransportDepart(uint16 boundary, uint16 zone); // ship/boat is leaving, passengers need to be collected - void TOTDChange(TIMETYPE TOTD); // process the world's reactions to changing time of day + void TOTDChange(vanadiel_time::TOTD TOTD); // process the world's reactions to changing time of day void WeatherChange(WEATHER weather); void MusicChange(uint16 BlockID, uint16 MusicTrackID); void PushPacket(CBaseEntity*, GLOBAL_MESSAGE_TYPE, const std::unique_ptr&); // send a global package within the zone - void ZoneServer(time_point tick); + void ZoneServer(timer::time_point tick); CZone* GetZone(); @@ -115,15 +117,15 @@ class CZoneEntities std::set m_charTargIds; // sorted set of targids for characters std::set m_dynamicTargIds; // sorted set of targids for dynamic entities - std::vector> m_dynamicTargIdsToDelete; // list of targids pending deletion at a later date + std::vector> m_dynamicTargIdsToDelete; // list of targids pending deletion at a later date - time_point m_EffectCheckTime{ server_clock::now() }; + timer::time_point m_EffectCheckTime{ timer::now() }; - time_point m_computeTime{ server_clock::now() }; - uint16 m_lastCharComputeTargId{ 0 }; + timer::time_point m_computeTime{ timer::now() }; + uint16 m_lastCharComputeTargId{ 0 }; - time_point m_charPersistTime{ server_clock::now() }; - uint16 m_lastCharPersistTargId{ 0 }; + timer::time_point m_charPersistTime{ timer::now() }; + uint16 m_lastCharPersistTargId{ 0 }; // // Intermediate collections for use inside ZoneServer diff --git a/src/map/zone_instance.cpp b/src/map/zone_instance.cpp index 83b5b44aba2..67591379ba5 100644 --- a/src/map/zone_instance.cpp +++ b/src/map/zone_instance.cpp @@ -157,7 +157,7 @@ void CZoneInstance::DecreaseZoneCounter(CCharEntity* PChar) { if (!(PInstance->Failed() || PInstance->Completed())) { - PInstance->SetWipeTime(PInstance->GetElapsedTime(server_clock::now())); + PInstance->SetWipeTime(PInstance->GetElapsedTime(timer::now())); } } } @@ -217,7 +217,7 @@ void CZoneInstance::IncreaseZoneCounter(CCharEntity* PChar) if (PChar->PInstance->GetLevelCap() > 0) { - PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, PChar->PInstance->GetLevelCap(), 0, 0)); + PChar->StatusEffectContainer->AddStatusEffect(new CStatusEffect(EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_RESTRICTION, PChar->PInstance->GetLevelCap(), 0s, 0s)); } if (PChar->PInstance->CheckFirstEntry(PChar->id)) @@ -323,7 +323,7 @@ void CZoneInstance::SpawnTransport(CCharEntity* PChar) } } -void CZoneInstance::TOTDChange(TIMETYPE TOTD) +void CZoneInstance::TOTDChange(vanadiel_time::TOTD TOTD) { TracyZoneScoped; for (const auto& PInstance : m_InstanceList) @@ -382,7 +382,7 @@ void CZoneInstance::WideScan(CCharEntity* PChar, uint16 radius) } } -void CZoneInstance::ZoneServer(time_point tick) +void CZoneInstance::ZoneServer(timer::time_point tick) { TracyZoneScoped; diff --git a/src/map/zone_instance.h b/src/map/zone_instance.h index 02b37b10248..53525798877 100644 --- a/src/map/zone_instance.h +++ b/src/map/zone_instance.h @@ -55,12 +55,13 @@ class CZoneInstance : public CZone virtual void FindPartyForMob(CBaseEntity* PEntity) override; // looking for a party for the monster virtual void TransportDepart(uint16 boundary, uint16 zone) override; // ship/boat is leaving, passengers need to be collected - virtual void TOTDChange(TIMETYPE TOTD) override; // process the world's reactions to changing time of day + virtual void TOTDChange(vanadiel_time::TOTD TOTD) override; // process the world's reactions to changing time of day + virtual void PushPacket(CBaseEntity*, GLOBAL_MESSAGE_TYPE, const std::unique_ptr&) override; // send a global package within the zone virtual void UpdateEntityPacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask, bool alwaysInclude = false) override; - virtual void ZoneServer(time_point tick) override; + virtual void ZoneServer(timer::time_point tick) override; virtual void CheckTriggerAreas() override; void ForEachChar(std::function const& func) override; diff --git a/src/search/search_handler.cpp b/src/search/search_handler.cpp index 318e20aefc9..f6fc63a0598 100644 --- a/src/search/search_handler.cpp +++ b/src/search/search_handler.cpp @@ -22,6 +22,7 @@ #include "search_handler.h" #include "common/md52.h" +#include "common/timer.h" #include "common/utils.h" #include "data_loader.h" @@ -76,7 +77,7 @@ void search_handler::start() { if (socket_.lowest_layer().is_open()) { - deadline_.expires_after(std::chrono::milliseconds(10000)); // AH searches can take quite a while + deadline_.expires_after(10s); // AH searches can take quite a while deadline_.async_wait(std::bind(&search_handler::checkDeadline, this, shared_from_this())); do_read(); @@ -907,7 +908,7 @@ void search_handler::addToUsedIPAddresses(std::string const& ipAddressStr) void search_handler::checkDeadline(std::shared_ptr self) // self to keep the object alive { - if (std::chrono::steady_clock::now() > deadline_.expiry()) + if (timer::now() > deadline_.expiry()) { DebugSocketsFmt("Socket timed out from {}", ipAddress); socket_.cancel(); diff --git a/src/world/daily_tally.cpp b/src/world/daily_tally.cpp index 1f84c82f2ff..36a0273c86d 100644 --- a/src/world/daily_tally.cpp +++ b/src/world/daily_tally.cpp @@ -30,6 +30,10 @@ namespace dailytally { void UpdateDailyTallyPoints() { + if (!settings::get("main.ENABLE_DAILY_TALLY")) + { + return; + } int32 dailyTallyLimit = std::clamp(settings::get("main.DAILY_TALLY_LIMIT"), std::numeric_limits::min(), std::numeric_limits::max()); int32 dailyTallyAmount = std::clamp(settings::get("main.DAILY_TALLY_AMOUNT"), std::numeric_limits::min(), std::numeric_limits::max()); diff --git a/src/world/http_server.cpp b/src/world/http_server.cpp index 1bc7ca0cdbb..194b2be62be 100644 --- a/src/world/http_server.cpp +++ b/src/world/http_server.cpp @@ -192,7 +192,7 @@ HTTPServer::~HTTPServer() void HTTPServer::LockingUpdate() { - auto now = server_clock::now(); + auto now = timer::now(); if (now < (m_lastUpdate.load() + 60s)) { return; diff --git a/src/world/http_server.h b/src/world/http_server.h index 948992a2bd7..af7c162185d 100644 --- a/src/world/http_server.h +++ b/src/world/http_server.h @@ -23,6 +23,7 @@ #include "common/logging.h" #include "common/synchronized.h" +#include "common/timer.h" #include "map/zone.h" @@ -39,8 +40,8 @@ class HTTPServer void LockingUpdate(); private: - httplib::Server m_httpServer; - std::atomic m_lastUpdate; + httplib::Server m_httpServer; + std::atomic m_lastUpdate; struct APIDataCache { diff --git a/src/world/time_server.cpp b/src/world/time_server.cpp index 73f719c5613..82271fa3d75 100644 --- a/src/world/time_server.cpp +++ b/src/world/time_server.cpp @@ -30,82 +30,101 @@ #include "daily_tally.h" #include "world_server.h" -int32 time_server(time_point tick, CTaskManager::CTask* PTask) +int32 time_server(timer::time_point tick, CTaskManager::CTask* PTask) { TracyZoneScoped; + // Track elapsed ticks. + static auto tickNum = 0; + ++tickNum; - TIMETYPE VanadielTOTD = CVanaTime::getInstance()->SyncTime(); - WorldServer* worldServer = std::any_cast(PTask->m_data); + WorldServer* worldServer = std::any_cast(PTask->m_data); - // Weekly update for conquest (sunday at midnight) - static time_point lastConquestTally = tick - 1h; - static time_point lastConquestUpdate = tick - 1h; - if (CVanaTime::getInstance()->getJstWeekDay() == 1 && CVanaTime::getInstance()->getJstHour() == 0 && CVanaTime::getInstance()->getJstMinute() == 0) + // Earth-based ticks. + // Uses the JST equivalent of the current timer tick. (steady_clock -> system_clock) + + // Earth time points + const auto jstTime = earth_time::time_point(timer::to_utc(tick)); + const auto jstHour = earth_time::jst::get_hour(jstTime); + const auto jstWeekday = earth_time::jst::get_weekday(jstTime); + + // Static variable for the next tick + static auto nextHourlyTick = std::chrono::ceil(jstTime); + + // Hourly ticks + if (jstTime >= nextHourlyTick) { - if (tick > (lastConquestTally + 1h)) + ShowDebugFmt("1-hour tick... (current tick: {})", tickNum); + if (jstHour == 0) { - worldServer->conquestSystem_->updateWeekConquest(); - lastConquestTally = tick; + // Daily tick (midnight JST) + ShowDebugFmt("Daily tick... (current tick: {})", tickNum); + if (jstWeekday == 1) + { + // Weekly tick (Monday JST) + ShowDebugFmt("Weekly tick... (current tick: {})", tickNum); + worldServer->conquestSystem_->updateWeekConquest(); + } + else + { + // This should happen every midnight except Monday. + worldServer->conquestSystem_->updateHourlyConquest(); + } + dailytally::UpdateDailyTallyPoints(); } - } - // Hourly conquest update - else if (CVanaTime::getInstance()->getJstMinute() == 0) - { - if (tick > (lastConquestUpdate + 1h)) + else { + // This should happen hourly, except midnight. worldServer->conquestSystem_->updateHourlyConquest(); - lastConquestUpdate = tick; } - } + // 1-hour tick (including every midnight) - // Vanadiel Hour - static time_point lastVHourlyUpdate = tick - 4800ms; - if (CVanaTime::getInstance()->getMinute() == 0) - { - if (tick > (lastVHourlyUpdate + 4800ms)) + if (jstHour % 2 == 0) { - worldServer->conquestSystem_->updateVanaHourlyConquest(); - lastVHourlyUpdate = tick; - } - } - - // JST Midnight - static time_point lastTickedJstMidnight = tick - 1h; - if (CVanaTime::getInstance()->getJstHour() == 0 && CVanaTime::getInstance()->getJstMinute() == 0) - { - if (tick > (lastTickedJstMidnight + 1h)) - { - if (settings::get("main.ENABLE_DAILY_TALLY")) + // 2-hour tick + ShowDebugFmt("2-hour tick... (current tick: {})", tickNum); + if (jstHour % 4 == 0) { - dailytally::UpdateDailyTallyPoints(); + // 4-hour tick + ShowDebugFmt("4-hour tick... (current tick: {})", tickNum); } - - lastTickedJstMidnight = tick; } + + nextHourlyTick = std::chrono::ceil(jstTime); } - // 4-hour RoE Timed blocks - static time_point lastTickedRoeBlock = tick - 1h; - if (CVanaTime::getInstance()->getJstHour() % 4 == 0 && CVanaTime::getInstance()->getJstMinute() == 0) + // Vana'diel-based ticks. + // Uses the Vana'diel time equivalent of the current JST time. (steady_clock -> system_clock -> vanadiel_clock) + // Note: Vana'diel minute is equal to the tick interval (2400ms). It is possible to miss a minute if there is + // variance in the tick time. + + // Vana'diel time points + const auto vanaTime = vanadiel_time::from_earth_time(jstTime); + const auto vanaTotd = vanadiel_time::get_totd(vanaTime); + const auto vanaHour = vanadiel_time::get_hour(vanaTime); + + // Static variables for the next tick + static auto nextVHourlyUpdate = std::chrono::ceil(vanaTime); + static auto prevTotd = vanaTotd; + + if (vanaTime >= nextVHourlyUpdate) { - if (tick > (lastTickedRoeBlock + 1h)) + // Vana'diel Hour + worldServer->conquestSystem_->updateVanaHourlyConquest(); + + if (vanaHour == 0) { - lastTickedRoeBlock = tick; + // Vana'diel Day + ShowDebugFmt("Vana'diel day tick... (current tick: {})", tickNum); } - } - // Vanadiel Day - static time_point lastVDailyUpdate = tick - 4800ms; - if (CVanaTime::getInstance()->getHour() == 0 && CVanaTime::getInstance()->getMinute() == 0) - { - if (tick > (lastVDailyUpdate + 4800ms)) + if (vanaTotd != prevTotd) { - lastVDailyUpdate = tick; + // MIDNIGHT -> NEWDAY -> DAWN -> DAY -> DUSK -> EVENING -> NIGHT + + prevTotd = vanaTotd; } - } - if (VanadielTOTD != TIME_NONE) - { + nextVHourlyUpdate = std::chrono::ceil(vanaTime); } return 0; diff --git a/src/world/time_server.h b/src/world/time_server.h index 10f9329f67a..f9ef2165aec 100644 --- a/src/world/time_server.h +++ b/src/world/time_server.h @@ -24,4 +24,4 @@ #include "common/cbasetypes.h" #include "common/task_manager.h" -int32 time_server(time_point tick, CTaskManager::CTask* PTask); +int32 time_server(timer::time_point tick, CTaskManager::CTask* PTask); diff --git a/src/world/world_server.cpp b/src/world/world_server.cpp index 6133625b2a8..ed48b858f82 100644 --- a/src/world/world_server.cpp +++ b/src/world/world_server.cpp @@ -23,6 +23,7 @@ #include "common/application.h" #include "common/logging.h" +#include "common/timer.h" #include "besieged_system.h" #include "campaign_system.h" @@ -35,9 +36,9 @@ namespace { - static constexpr auto kTimeServerTickTime = 2400ms; - static constexpr auto kPumpQueuesTime = 250ms; - static constexpr auto kMainTickTime = 200ms; + static constexpr auto kTimeServerTickInterval = 2400ms; + static constexpr auto kPumpQueuesTime = 250ms; + static constexpr auto kMainLoopInterval = 200ms; } // namespace /* @@ -56,7 +57,7 @@ void pump_queues(WorldServer* worldServer, asio::steady_timer* timer) } */ -int32 pump_queues(time_point tick, CTaskManager::CTask* PTask) +int32 pump_queues(timer::time_point tick, CTaskManager::CTask* PTask) { TracyZoneScoped; @@ -76,10 +77,10 @@ WorldServer::WorldServer(int argc, char** argv) , httpServer_(std::make_unique()) { // Tasks - CTaskManager::getInstance()->AddTask("time_server", server_clock::now(), this, CTaskManager::TASK_INTERVAL, kTimeServerTickTime, time_server); + CTaskManager::getInstance()->AddTask("time_server", timer::now(), this, CTaskManager::TASK_INTERVAL, kTimeServerTickInterval, time_server); // TODO: Make this more reactive than a polling job - CTaskManager::getInstance()->AddTask("pump_queues", server_clock::now(), this, CTaskManager::TASK_INTERVAL, kPumpQueuesTime, pump_queues); + CTaskManager::getInstance()->AddTask("pump_queues", timer::now(), this, CTaskManager::TASK_INTERVAL, kPumpQueuesTime, pump_queues); // asio::steady_timer timeServerTimer(io_context_, kPumpQueuesTime); // timeServerTimer.async_wait(std::bind(&pump_queues, this, &timeServerTimer)); @@ -97,9 +98,9 @@ void WorldServer::run() while (Application::isRunning()) { - const auto tickStart = server_clock::now(); + const auto tickStart = timer::now(); const auto tasksDuration = CTaskManager::getInstance()->doExpiredTasks(tickStart); - const auto sleepFor = kMainTickTime - tasksDuration; + const auto sleepFor = kMainLoopInterval - tasksDuration; std::this_thread::sleep_for(sleepFor); } } diff --git a/tools/ci/check_lua_binding_usage.py b/tools/ci/check_lua_binding_usage.py index c079c4fe087..5f2c91c19a4 100644 --- a/tools/ci/check_lua_binding_usage.py +++ b/tools/ci/check_lua_binding_usage.py @@ -5,6 +5,7 @@ import glob import os import re +import regex function_names = [] @@ -131,8 +132,10 @@ def main(): line = line.split("--", 1)[0] # Don't look inside strings (replace with placeholder) - line = re.sub(r'\"([^\"]*?)\"', "strVal", line) - line = re.sub(r"\'([^\"]*?)\'", "strVal", line) + quote_regex = regex.compile( + r"\"(([^\"\"]+)|(?R))*+\"|\'(([^\'\']+)|(?R))*+\'", re.S + ) + line = regex.sub(quote_regex, "strVal", line) # Try and ignore function definitions line = line.split("function", 1)[0] diff --git a/tools/run_clang_format.sh b/tools/run_clang_format.sh index eabcab5babe..91facdff77e 100644 --- a/tools/run_clang_format.sh +++ b/tools/run_clang_format.sh @@ -1,3 +1,3 @@ # Run from repo root -for f in $(find src/ -name '*.h' -or -name '*.cpp'); do clang-format-15 -style=file -i $f; done -for f in $(find modules/ -name '*.h' -or -name '*.cpp'); do clang-format-15 -style=file -i $f; done +for f in $(find src/ -name '*.h' -or -name '*.cpp'); do clang-format-18 -style=file -i $f; done +for f in $(find modules/ -name '*.h' -or -name '*.cpp'); do clang-format-18 -style=file -i $f; done