285 lines
11 KiB
Lua
285 lines
11 KiB
Lua
require('scripts/globals/abyssea')
|
|
require('scripts/globals/gear_sets')
|
|
require('scripts/globals/quests')
|
|
require('scripts/globals/teleports')
|
|
require('scripts/events/login_campaign')
|
|
-----------------------------------
|
|
require('scripts/quests/full_speed_ahead')
|
|
-----------------------------------
|
|
|
|
local startingRaceInfo =
|
|
{
|
|
[xi.race.HUME_M ] = { gear = { body = xi.item.HUME_TUNIC, hand = xi.item.HUME_M_GLOVES, leg = xi.item.HUME_SLACKS, feet = xi.item.HUME_M_BOOTS }, homeNation = xi.nation.BASTOK },
|
|
[xi.race.HUME_F ] = { gear = { body = xi.item.HUME_VEST, hand = xi.item.HUME_F_GLOVES, leg = xi.item.HUME_PANTS, feet = xi.item.HUME_F_BOOTS }, homeNation = xi.nation.BASTOK },
|
|
[xi.race.ELVAAN_M] = { gear = { body = xi.item.ELVAAN_JERKIN, hand = xi.item.ELVAAN_GLOVES, leg = xi.item.ELVAAN_M_CHAUSSES, feet = xi.item.ELVAAN_M_LEDELSENS }, homeNation = xi.nation.SANDORIA },
|
|
[xi.race.ELVAAN_F] = { gear = { body = xi.item.ELVAAN_BODICE, hand = xi.item.ELVAAN_GAUNTLETS, leg = xi.item.ELVAAN_F_CHAUSSES, feet = xi.item.ELVAAN_F_LEDELSENS }, homeNation = xi.nation.SANDORIA },
|
|
[xi.race.TARU_M ] = { gear = { body = xi.item.TARUTARU_KAFTAN, hand = xi.item.TARUTARU_MITTS, leg = xi.item.TARUTARU_BRACCAE, feet = xi.item.TARUTARU_CLOMPS }, homeNation = xi.nation.WINDURST },
|
|
[xi.race.TARU_F ] = { gear = { body = xi.item.TARUTARU_KAFTAN, hand = xi.item.TARUTARU_MITTS, leg = xi.item.TARUTARU_BRACCAE, feet = xi.item.TARUTARU_CLOMPS }, homeNation = xi.nation.WINDURST },
|
|
[xi.race.MITHRA ] = { gear = { body = xi.item.MITHRAN_SEPARATES, hand = xi.item.MITHRAN_GAUNTLETS, leg = xi.item.MITHRAN_LOINCLOTH, feet = xi.item.MITHRAN_GAITERS }, homeNation = xi.nation.WINDURST },
|
|
[xi.race.GALKA ] = { gear = { body = xi.item.GALKAN_SURCOAT, hand = xi.item.GALKAN_BRACERS, leg = xi.item.GALKAN_BRAGUETTE, feet = xi.item.GALKAN_SANDALS }, homeNation = xi.nation.BASTOK },
|
|
}
|
|
|
|
local startingNationInfo =
|
|
{
|
|
[xi.nation.SANDORIA] = { ring = xi.item.SAN_DORIAN_RING, map = xi.ki.MAP_OF_THE_SAN_DORIA_AREA },
|
|
[xi.nation.BASTOK ] = { ring = xi.item.BASTOKAN_RING, map = xi.ki.MAP_OF_THE_BASTOK_AREA },
|
|
[xi.nation.WINDURST] = { ring = xi.item.WINDURSTIAN_RING, map = xi.ki.MAP_OF_THE_WINDURST_AREA },
|
|
}
|
|
|
|
local startingJobGear =
|
|
{
|
|
[xi.job.WAR] = { xi.item.ONION_SWORD },
|
|
[xi.job.MNK] = { xi.item.WHITE_BELT },
|
|
[xi.job.WHM] = { xi.item.ONION_ROD, xi.item.SCROLL_OF_CURE_EX },
|
|
[xi.job.BLM] = { xi.item.ONION_STAFF, xi.item.SCROLL_OF_STONE_EX },
|
|
[xi.job.RDM] = { xi.item.ONION_DAGGER, xi.item.SCROLL_OF_DIA_EX },
|
|
[xi.job.THF] = { xi.item.ONION_KNIFE },
|
|
}
|
|
|
|
-----------------------------------
|
|
-- public functions
|
|
-----------------------------------
|
|
xi = xi or {}
|
|
xi.player = {}
|
|
|
|
xi.player.charCreate = function(player)
|
|
local race = player:getRace()
|
|
local raceInfo = startingRaceInfo[race]
|
|
local nation = player:getNation()
|
|
local nationInfo = startingNationInfo[nation]
|
|
|
|
-- add race-specific starting gear
|
|
for _, v in pairs(raceInfo.gear) do
|
|
if not player:hasItem(v) then
|
|
player:addItem(v)
|
|
player:equipItem(v)
|
|
end
|
|
end
|
|
|
|
-- add job-specific starting gear
|
|
for _, v in pairs(startingJobGear[player:getMainJob()]) do
|
|
if not player:hasItem(v) then
|
|
player:addItem(v)
|
|
end
|
|
end
|
|
|
|
-- add nation-specific map
|
|
player:addKeyItem(nationInfo.map)
|
|
|
|
-- add job-emote Key items
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_WARRIOR)
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_MONK)
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_WHITE_MAGE)
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_BLACK_MAGE)
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_RED_MAGE)
|
|
player:addKeyItem(xi.ki.JOB_GESTURE_THIEF)
|
|
|
|
-- add nation- and race-specific ring
|
|
if nation == raceInfo.homeNation and not player:hasItem(nationInfo.ring) then
|
|
player:addItem(nationInfo.ring)
|
|
end
|
|
|
|
-- unlock advanced jobs
|
|
if xi.settings.main.ADVANCED_JOB_LEVEL == 0 then
|
|
for i = xi.job.PLD, xi.job.SCH do
|
|
player:unlockJob(i)
|
|
end
|
|
end
|
|
|
|
-- unlock subjob
|
|
if xi.settings.main.SUBJOB_QUEST_LEVEL == 0 then
|
|
player:unlockJob(0)
|
|
end
|
|
|
|
-- give all maps
|
|
if xi.settings.main.ALL_MAPS == 1 then
|
|
for i = xi.ki.MAP_OF_THE_SAN_DORIA_AREA, xi.ki.MAP_OF_DIO_ABDHALJS_GHELSBA do
|
|
player:addKeyItem(i)
|
|
end
|
|
|
|
for i = xi.ki.MAP_OF_AL_ZAHBI, xi.ki.MAP_OF_RAKAZNAR do
|
|
player:addKeyItem(i)
|
|
end
|
|
|
|
for i = xi.ki.MAP_OF_RALA_WATERWAYS_U, xi.ki.MAP_OF_RAKAZNAR_U do
|
|
player:addKeyItem(i)
|
|
end
|
|
|
|
for i = xi.ki.MAP_OF_ESCHA_ZITAH, xi.ki.MAP_OF_REISENJIMA do
|
|
player:addKeyItem(i)
|
|
end
|
|
end
|
|
|
|
-- set initial level cap
|
|
if xi.settings.main.INITIAL_LEVEL_CAP ~= 50 then
|
|
player:setLevelCap(xi.settings.main.INITIAL_LEVEL_CAP)
|
|
end
|
|
|
|
-- increase starting inventory
|
|
if xi.settings.main.START_INVENTORY > 30 then
|
|
player:changeContainerSize(xi.inv.INVENTORY, xi.settings.main.START_INVENTORY - 30)
|
|
player:changeContainerSize(xi.inv.MOGSATCHEL, xi.settings.main.START_INVENTORY) -- Default satchel size is zero, so just set it to the setting size.
|
|
end
|
|
|
|
--[[
|
|
For some intermittent reason m_ZoneList ends up empty on characters, which is
|
|
possibly also why they lose key items. When that happens, CharCreate will be run and
|
|
they end up losing their gil to the code below. Added a conditional to hopefully
|
|
prevent that until the bug is fixed. Used the if instead of addGil to prevent abuse
|
|
on servers with very high values of START_GIL, I guess.
|
|
--]]
|
|
|
|
if player:getGil() < xi.settings.main.START_GIL then
|
|
player:setGil(xi.settings.main.START_GIL)
|
|
end
|
|
|
|
if xi.settings.main.NEW_CHARACTER_CUTSCENE == 0 then -- Do things that would normally be done in opening cutscene.
|
|
player:addItem(xi.item.ADVENTURER_COUPON)
|
|
player:setHomePoint()
|
|
end
|
|
|
|
player:addTitle(xi.title.NEW_ADVENTURER)
|
|
player:setCharVar('HQuest[moghouseExpo]notSeen', 1) -- needs Moghouse intro
|
|
player:setCharVar('spokeKindlix', 1) -- Kindlix introduction
|
|
player:setCharVar('spokePyropox', 1) -- Pyropox introduction
|
|
player:setCharVar('EinherjarIntro', 1) -- Has not seen Einherjar intro
|
|
player:setNewPlayer(true) -- apply new player flag
|
|
end
|
|
|
|
-- called by core after a player logs into the server or zones
|
|
xi.player.onGameIn = function(player, firstLogin, zoning)
|
|
if not zoning then
|
|
-- things checked ONLY during logon go here
|
|
if firstLogin then
|
|
xi.player.charCreate(player)
|
|
end
|
|
else
|
|
-- things checked ONLY during zone in go here
|
|
if
|
|
player:getLocalVar('gameLogin') == 1 and
|
|
xi.abyssea.isInAbysseaZone(player) and
|
|
not player:hasStatusEffect(xi.effect.VISITANT)
|
|
then
|
|
local zoneID = player:getZoneID()
|
|
local ID = zones[zoneID]
|
|
|
|
player:messageSpecial(ID.text.ABYSSEA_TIME_OFFSET + 8)
|
|
player:setPos(unpack(xi.abyssea.exitPositions[zoneID]))
|
|
end
|
|
end
|
|
|
|
local zoneID = player:getZoneID()
|
|
local questVars = player:getCharVarsWithSuffix(']mustZone')
|
|
|
|
for tag, value in pairs(questVars) do
|
|
if value ~= zoneID then
|
|
player:setCharVar(tag, 0)
|
|
end
|
|
end
|
|
|
|
-- Abyssea starting quest should be flagged when expansion is active
|
|
if
|
|
xi.settings.main.ENABLE_ABYSSEA == 1 and
|
|
player:getQuestStatus(xi.questLog.ABYSSEA, xi.quest.id.abyssea.A_JOURNEY_BEGINS) == xi.questStatus.QUEST_AVAILABLE
|
|
then
|
|
player:addQuest(xi.questLog.ABYSSEA, xi.quest.id.abyssea.A_JOURNEY_BEGINS)
|
|
end
|
|
|
|
-- This is for migration safety only, and should be removed at a later date
|
|
if
|
|
player:hasCompletedQuest(xi.questLog.ABYSSEA, xi.quest.id.abyssea.A_JOURNEY_BEGINS) and
|
|
player:getTraverserEpoch() == 0
|
|
then
|
|
player:setTraverserEpoch()
|
|
end
|
|
|
|
-- apply mods from gearsets (scripts/globals/gear_sets.lua)
|
|
xi.gear_sets.checkForGearSet(player)
|
|
|
|
-- god mode
|
|
if player:getCharVar('GodMode') == 1 then
|
|
player:addStatusEffect(xi.effect.MAX_HP_BOOST, { power = 1000, origin = player })
|
|
player:addStatusEffect(xi.effect.MAX_MP_BOOST, { power = 1000, origin = player })
|
|
player:addStatusEffect(xi.effect.MIGHTY_STRIKES, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.HUNDRED_FISTS, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.CHAINSPELL, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.PERFECT_DODGE, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.INVINCIBLE, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.ELEMENTAL_SFORZO, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.MANAFONT, { power = 1, origin = player })
|
|
player:addStatusEffect(xi.effect.REGAIN, { power = 300, origin = player })
|
|
player:addStatusEffect(xi.effect.REFRESH, { power = 99, origin = player })
|
|
player:addStatusEffect(xi.effect.REGEN, { power = 99, origin = player })
|
|
player:addMod(xi.mod.RACC, 2500)
|
|
player:addMod(xi.mod.RATT, 2500)
|
|
player:addMod(xi.mod.ACC, 2500)
|
|
player:addMod(xi.mod.ATT, 2500)
|
|
player:addMod(xi.mod.MATT, 2500)
|
|
player:addMod(xi.mod.MACC, 2500)
|
|
player:addMod(xi.mod.RDEF, 2500)
|
|
player:addMod(xi.mod.DEF, 2500)
|
|
player:addMod(xi.mod.MDEF, 2500)
|
|
player:addHP(50000)
|
|
player:setMP(50000)
|
|
end
|
|
|
|
-- !immortal
|
|
if player:getCharVar('Immortal') == 1 then
|
|
player:setUnkillable(true)
|
|
end
|
|
|
|
-- !hide
|
|
if player:getCharVar('GMHidden') == 1 then
|
|
player:setGMHidden(true)
|
|
end
|
|
|
|
-- remember time player zoned in (e.g., to support zone-in delays)
|
|
player:setLocalVar('ZoneInTime', GetSystemTime())
|
|
player:setLocalVar('ZoningIn', 1)
|
|
|
|
-- Slight delay to ensure player is fully logged in
|
|
player:timer(2500, function(playerArg)
|
|
player:setLocalVar('ZoningIn', 0)
|
|
-- Login Campaign rewards points once daily
|
|
xi.events.loginCampaign.onGameIn(playerArg)
|
|
end)
|
|
|
|
-- Enforce that gameLogin is always set to 0 once this method exits
|
|
-- This assists with ensuring Abyssea visitant status is handled properly on logins
|
|
player:setLocalVar('gameLogin', 0)
|
|
end
|
|
|
|
xi.player.onPlayerDeath = function(player)
|
|
end
|
|
|
|
xi.player.onPlayerLevelUp = function(player)
|
|
end
|
|
|
|
xi.player.onPlayerLevelDown = function(player)
|
|
end
|
|
|
|
xi.player.onPlayerMount = function(player)
|
|
-- For PM3-3 The Road Forks. This value will be checked periodically, and break
|
|
-- the Mimeo Jewel should a player be mounted, zone, or disconnect.
|
|
if
|
|
player:getZoneID() == xi.zone.ATTOHWA_CHASM and
|
|
player:hasKeyItem(xi.ki.MIMEO_JEWEL)
|
|
then
|
|
player:messageSpecial(zones[xi.zone.ATTOHWA_CHASM].text.MIMEO_JEWEL_OFFSET + 4, xi.ki.MIMEO_JEWEL)
|
|
player:delKeyItem(xi.ki.MIMEO_JEWEL)
|
|
end
|
|
end
|
|
|
|
xi.player.onPlayerEmote = function(player, emoteId)
|
|
if
|
|
emoteId == xi.emote.CHEER and
|
|
player:hasStatusEffect(xi.effect.FULL_SPEED_AHEAD)
|
|
then
|
|
xi.fsa.onCheer(player)
|
|
end
|
|
end
|
|
|
|
xi.player.onPlayerVolunteer = function(player, text)
|
|
end
|
|
|
|
return xi.player
|