524 lines
20 KiB
Lua
524 lines
20 KiB
Lua
-----------------------------------
|
|
-- Carpenters' Landing Barge
|
|
-- https://www.bg-wiki.com/ffxi/Phanauet_Channel
|
|
-----------------------------------
|
|
xi = xi or {}
|
|
xi.barge = xi.barge or {}
|
|
|
|
local channelID = zones[xi.zone.PHANAUET_CHANNEL]
|
|
local landingID = zones[xi.zone.CARPENTERS_LANDING]
|
|
|
|
-- OOS = out of service
|
|
-- ARRIVE action is given until the boat has fully docked
|
|
-- DEPART action is given until the boat has fully disppaered in the distance
|
|
local actions =
|
|
{
|
|
ARRIVE = 0,
|
|
DEPART = 1,
|
|
ARRIVE_OOS = 2,
|
|
DEPART_OOS = 3,
|
|
}
|
|
|
|
-- Barge destinations
|
|
local destinations =
|
|
{
|
|
SOUTH_LANDING = 0,
|
|
CENTRAL_LANDING_EMFEA = 1,
|
|
NORTH_LANDING = 2,
|
|
CENTRAL_LANDING = 3,
|
|
}
|
|
|
|
-- Locations for timekeeper NPCs
|
|
xi.barge.location =
|
|
{
|
|
NORTH_LANDING = 1,
|
|
CENTRAL_LANDING = 2,
|
|
SOUTH_LANDING = 3,
|
|
PHANAUET_CHANNEL = 4,
|
|
}
|
|
|
|
-- times are minutes past midnight, since the cycle is every 1440 minutes, and aligns with the transports.sql entries
|
|
-- time for arrivalStart: time_offset
|
|
-- time for arrivalEnd: time_offset + time_anim_arrive
|
|
-- time for departStart: time_offset + time_anim_arrive + time_waiting
|
|
-- time for departEnd: time_offset + time_anim_arrive + time_waiting + time_anim_depart
|
|
-- time for ride in the channel to end: time_offset + time_anim_arrive - 10
|
|
local bargeSchedule =
|
|
{
|
|
[xi.barge.location.NORTH_LANDING] =
|
|
{
|
|
{ endTime = utils.timeStringToMinutes('16:00'), action = actions.ARRIVE_OOS, route = destinations.CENTRAL_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('16:21'), action = actions.DEPART_OOS, route = destinations.CENTRAL_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('16:45'), action = actions.ARRIVE, route = destinations.CENTRAL_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('17:40'), action = actions.DEPART, route = destinations.CENTRAL_LANDING },
|
|
},
|
|
[xi.barge.location.CENTRAL_LANDING] =
|
|
{
|
|
{ endTime = utils.timeStringToMinutes('04:35'), action = actions.ARRIVE, route = destinations.SOUTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('05:25'), action = actions.DEPART, route = destinations.SOUTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('19:15'), action = actions.ARRIVE, route = destinations.SOUTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('20:05'), action = actions.DEPART, route = destinations.SOUTH_LANDING },
|
|
},
|
|
[xi.barge.location.SOUTH_LANDING] =
|
|
{
|
|
{ endTime = utils.timeStringToMinutes('00:15'), action = actions.ARRIVE, route = destinations.CENTRAL_LANDING_EMFEA },
|
|
{ endTime = utils.timeStringToMinutes('01:05'), action = actions.DEPART, route = destinations.CENTRAL_LANDING_EMFEA },
|
|
{ endTime = utils.timeStringToMinutes('08:55'), action = actions.ARRIVE_OOS, route = destinations.NORTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('09:06'), action = actions.DEPART_OOS, route = destinations.NORTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('09:35'), action = actions.ARRIVE, route = destinations.NORTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('10:25'), action = actions.DEPART, route = destinations.NORTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('23:35'), action = actions.ARRIVE_OOS, route = destinations.CENTRAL_LANDING_EMFEA },
|
|
{ endTime = utils.timeStringToMinutes('23:56'), action = actions.DEPART_OOS, route = destinations.CENTRAL_LANDING_EMFEA },
|
|
},
|
|
[xi.barge.location.PHANAUET_CHANNEL] =
|
|
{
|
|
{ endTime = utils.timeStringToMinutes('04:35'), route = destinations.CENTRAL_LANDING_EMFEA },
|
|
{ endTime = utils.timeStringToMinutes('08:55'), route = destinations.SOUTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('16:00'), route = destinations.NORTH_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('19:15'), route = destinations.CENTRAL_LANDING },
|
|
{ endTime = utils.timeStringToMinutes('23:35'), route = destinations.SOUTH_LANDING },
|
|
},
|
|
}
|
|
|
|
local getNextEvent = function(currentTime, schedule)
|
|
local nextEvent = schedule[1]
|
|
if
|
|
schedule[#schedule].endTime <= currentTime or -- currentTime after the last event
|
|
schedule[1].endTime > currentTime -- currentTime before first event
|
|
then
|
|
-- next event is first of the day
|
|
return schedule[1]
|
|
end
|
|
|
|
local prevEventEndTime = 0
|
|
for i, currEvent in ipairs(schedule) do
|
|
if
|
|
prevEventEndTime <= currentTime and
|
|
currEvent.endTime > currentTime
|
|
then
|
|
nextEvent = currEvent
|
|
|
|
break
|
|
end
|
|
|
|
prevEventEndTime = currEvent.endTime
|
|
end
|
|
|
|
return nextEvent
|
|
end
|
|
|
|
xi.barge.timekeeperOnTrigger = function(player, location, eventId)
|
|
local schedule = bargeSchedule[location]
|
|
|
|
if not schedule then
|
|
printf('[warning] bad location %i in xi.barge.timekeeperOnTrigger', location)
|
|
|
|
return
|
|
end
|
|
|
|
local currentTime = VanadielHour() * 60 + VanadielMinute()
|
|
local nextEvent = getNextEvent(currentTime, schedule)
|
|
|
|
local gameMins = nextEvent.endTime - currentTime
|
|
if nextEvent.endTime < currentTime then
|
|
-- next event is before current time because it's near the end of the day, add a cycle
|
|
-- nextEvent.endTime - currentTime underflows so add 1440 first
|
|
gameMins = 1440 + nextEvent.endTime - currentTime
|
|
end
|
|
|
|
local earthSecs = gameMins * 60 / 25 -- one earth second is 25 game seconds
|
|
|
|
if location == xi.barge.location.PHANAUET_CHANNEL then
|
|
-- earthSecs is passed to dock timekeepers and they floor to report minutes, do the same here
|
|
local earthMins = math.floor(earthSecs / 60)
|
|
local gameHours = math.floor(gameMins / 60)
|
|
if earthMins ~= 0 then
|
|
player:startEvent(eventId, earthMins, gameHours, nextEvent.route)
|
|
else
|
|
-- arriving shortly
|
|
player:startEvent(eventId - 1, 0, 0, nextEvent.route)
|
|
end
|
|
else
|
|
player:startEvent(eventId, earthSecs, nextEvent.action, 0, nextEvent.route)
|
|
end
|
|
end
|
|
|
|
-- defines which NPCs to display for a route
|
|
-- # is the offset from each ID.npc entry
|
|
local npcList =
|
|
{
|
|
[destinations.NORTH_LANDING] =
|
|
{
|
|
-- Roi, Luquillaue, Ineuteniace
|
|
tonberry = 1,
|
|
timekeeper = 0,
|
|
rider = 1,
|
|
},
|
|
[destinations.CENTRAL_LANDING] =
|
|
{
|
|
-- Roi, Luquillaue, Eunirange
|
|
tonberry = 1,
|
|
timekeeper = 1,
|
|
rider = 1,
|
|
},
|
|
[destinations.SOUTH_LANDING] =
|
|
{
|
|
-- Riche, Laiteconce, Ineuteniace
|
|
tonberry = 0,
|
|
timekeeper = 0,
|
|
rider = 0,
|
|
},
|
|
[destinations.CENTRAL_LANDING_EMFEA] =
|
|
{
|
|
-- Riche, Laiteconce, Eunirange
|
|
tonberry = 0,
|
|
timekeeper = 1,
|
|
rider = 0,
|
|
},
|
|
}
|
|
|
|
-- The timekeeper narrates the trip while the barge is in the channel. Keyed by route rather
|
|
-- than by leg, because both South Landing legs run the same Newtpool script at the same
|
|
-- offsets. `before` is minutes ahead of the leg's endTime in bargeSchedule. Lines flagged
|
|
-- `emote` are shown without a speaker name. From captures.
|
|
local routeDialogue =
|
|
{
|
|
[destinations.NORTH_LANDING] =
|
|
{
|
|
{ before = 323, messageId = channelID.text.NORTH_GREETING, emote = false },
|
|
{ before = 305, messageId = channelID.text.NORTH_MAIN_CANAL, emote = false },
|
|
{ before = 281, messageId = channelID.text.NORTH_WATERFALL, emote = false },
|
|
{ before = 215, messageId = channelID.text.NORTH_LINE_CAUGHT, emote = true },
|
|
{ before = 125, messageId = channelID.text.NORTH_CURRENTS_MEET, emote = false },
|
|
{ before = 75, messageId = channelID.text.NORTH_CHILLY_AIR, emote = false },
|
|
{ before = 14, messageId = channelID.text.NORTH_ARRIVING_NORTH, emote = false },
|
|
},
|
|
[destinations.CENTRAL_LANDING] =
|
|
{
|
|
{ before = 88, messageId = channelID.text.CENTRAL_GREETING },
|
|
{ before = 74, messageId = channelID.text.CENTRAL_CRISP_BREEZE },
|
|
{ before = 41, messageId = channelID.text.CENTRAL_FORK_IN_CANAL },
|
|
{ before = 32, messageId = channelID.text.CENTRAL_SCRUMPTIOUS_LIZARDS },
|
|
{ before = 18, messageId = channelID.text.CENTRAL_ARRIVING_CENTRAL },
|
|
},
|
|
[destinations.SOUTH_LANDING] =
|
|
{
|
|
{ before = 190, messageId = channelID.text.NEWTPOOL_GREETING },
|
|
{ before = 180, messageId = channelID.text.NEWTPOOL_CONVERGE },
|
|
{ before = 164, messageId = channelID.text.NEWTPOOL_LIZARDS },
|
|
{ before = 118, messageId = channelID.text.NEWTPOOL_PASSING_THROUGH },
|
|
{ before = 53, messageId = channelID.text.NEWTPOOL_EDGE_OF_POOL },
|
|
{ before = 14, messageId = channelID.text.NEWTPOOL_ARRIVING_SOUTH },
|
|
},
|
|
[destinations.CENTRAL_LANDING_EMFEA] =
|
|
{
|
|
{ before = 190, messageId = channelID.text.EMFEA_GREETING },
|
|
{ before = 175, messageId = channelID.text.EMFEA_AMPHIBIANS },
|
|
{ before = 149, messageId = channelID.text.EMFEA_NARROW_ROUTE },
|
|
{ before = 135, messageId = channelID.text.EMFEA_VARIETY_OF_LIFE },
|
|
{ before = 96, messageId = channelID.text.EMFEA_DANGEROUS_BRIDGE },
|
|
{ before = 52, messageId = channelID.text.EMFEA_NEWTS_AND_FROGS },
|
|
{ before = 21, messageId = channelID.text.EMFEA_ARRIVING_CENTRAL },
|
|
},
|
|
}
|
|
|
|
-- Each landing's timekeeper announces the barge docking and departing. From captures.
|
|
local dockAnnouncers =
|
|
{
|
|
{ location = xi.barge.location.NORTH_LANDING, npcId = landingID.npc.FELOURIE },
|
|
{ location = xi.barge.location.CENTRAL_LANDING, npcId = landingID.npc.RATOULLE },
|
|
{ location = xi.barge.location.SOUTH_LANDING, npcId = landingID.npc.CHUAIE },
|
|
}
|
|
|
|
local handleEntityVisibility = function(destination, zoneId)
|
|
local zone = GetZone(zoneId)
|
|
-- offset by one to avoid zero
|
|
if not zone or zone:getLocalVar('destinationEntities') == destination + 1 then
|
|
return
|
|
end
|
|
|
|
zone:setLocalVar('destinationEntities', destination + 1)
|
|
local ID = zones[zoneId]
|
|
local npcData = npcList[destination]
|
|
if not npcData then
|
|
-- should not be possible
|
|
return
|
|
end
|
|
|
|
local offsets =
|
|
{
|
|
tonberry = ID.npc.TONBERRY_OFFSET,
|
|
timekeeper = ID.npc.TIMEKEEPER_OFFSET,
|
|
rider = ID.npc.RIDER_OFFSET,
|
|
}
|
|
|
|
for k, v in pairs(npcData) do
|
|
for i = 0, 1 do
|
|
local npc = GetNPCByID(offsets[k] + i)
|
|
if npc then
|
|
if v == i then
|
|
npc:setStatus(xi.status.NORMAL)
|
|
else
|
|
npc:setStatus(xi.status.DISAPPEAR)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local dockEventData =
|
|
{
|
|
[destinations.NORTH_LANDING] =
|
|
{
|
|
-- transport ids from DB
|
|
transports = { 25 },
|
|
arrivalCsId = 11,
|
|
arrivalPos = { x = -303.166, y = -1.971, z = 504.964, rotation = 96 },
|
|
departEvent = 16,
|
|
kickEvent = 34,
|
|
triggerAreaId = 1,
|
|
},
|
|
[destinations.CENTRAL_LANDING] =
|
|
{
|
|
-- transport ids from DB
|
|
transports = { 21, 26 },
|
|
arrivalCsId = 10,
|
|
arrivalPos = { x = -137.275, y = -1.964, z = 60.265, rotation = 96 },
|
|
departEvent = 40,
|
|
kickEvent = 42,
|
|
triggerAreaId = 3,
|
|
},
|
|
[destinations.SOUTH_LANDING] =
|
|
{
|
|
-- transport ids from DB
|
|
transports = { 20, 23 },
|
|
arrivalCsId = 38,
|
|
arrivalPos = { x = 230.621, y = -1.987, z = -530.240, rotation = 129 },
|
|
departEvent = 14,
|
|
kickEvent = 33,
|
|
triggerAreaId = 2,
|
|
},
|
|
}
|
|
|
|
-- Aboard, the timekeeper narrates the current leg. At the landings, their timekeeper
|
|
-- announces the barge docking and departing. Nothing fires while a zone is empty.
|
|
xi.barge.onZoneTick = function(zone)
|
|
local currentTime = VanadielHour() * 60 + VanadielMinute()
|
|
|
|
-- A Vana'diel minute is 2.4 earth seconds, so only look once per minute rather than on
|
|
-- every tick. Offset by one to avoid zero, so midnight is not mistaken for unset.
|
|
if zone:getLocalVar('[barge]lastMessage') == currentTime + 1 then
|
|
return
|
|
end
|
|
|
|
zone:setLocalVar('[barge]lastMessage', currentTime + 1)
|
|
|
|
if zone:getID() == xi.zone.PHANAUET_CHANNEL then
|
|
local nextEvent = getNextEvent(currentTime, bargeSchedule[xi.barge.location.PHANAUET_CHANNEL])
|
|
local dialogue = routeDialogue[nextEvent.route]
|
|
if not dialogue then
|
|
return
|
|
end
|
|
|
|
for _, line in ipairs(dialogue) do
|
|
if nextEvent.endTime - line.before == currentTime then
|
|
local timekeeper = GetNPCByID(channelID.npc.TIMEKEEPER_OFFSET + npcList[nextEvent.route].timekeeper)
|
|
if timekeeper then
|
|
if line.emote then
|
|
timekeeper:messageText(timekeeper, line.messageId, false, 4)
|
|
else
|
|
timekeeper:messageText(timekeeper, line.messageId, true)
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
end
|
|
else
|
|
-- Out of service arrivals and departures are not announced.
|
|
for _, dock in ipairs(dockAnnouncers) do
|
|
for _, event in ipairs(bargeSchedule[dock.location]) do
|
|
local messageId = nil
|
|
|
|
if event.action == actions.ARRIVE and event.endTime == currentTime then
|
|
messageId = landingID.text.BARGE_HAS_ARRIVED
|
|
elseif event.action == actions.DEPART and event.endTime - 15 == currentTime then
|
|
messageId = landingID.text.BARGE_ABOUT_TO_DEPART
|
|
end
|
|
|
|
if messageId then
|
|
local timekeeper = GetNPCByID(dock.npcId)
|
|
if timekeeper then
|
|
timekeeper:messageText(timekeeper, messageId, true)
|
|
end
|
|
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
xi.barge.onZoneIn = function(player, prevZone)
|
|
local zoneId = player:getZoneID()
|
|
|
|
if zoneId == xi.zone.PHANAUET_CHANNEL then
|
|
-- Zoning into Phanauet Channel. Set destination charvar based on schedule.
|
|
local schedule = bargeSchedule[xi.barge.location.PHANAUET_CHANNEL]
|
|
local currentTime = VanadielHour() * 60 + VanadielMinute()
|
|
local nextEvent = getNextEvent(currentTime, schedule)
|
|
|
|
-- Saving as a charvar for use when zoning back into carpenter's landing
|
|
-- TODO should we reset the charvar to negative 1 when leaving a dock and only set this if the charvar is -1? This would block skipping legs by logging out
|
|
player:setCharVar('[barge]destinationDockId', nextEvent.route)
|
|
|
|
-- entity visibility only matters if a player zones in, set it now
|
|
handleEntityVisibility(nextEvent.route, player:getZoneID())
|
|
elseif
|
|
zoneId == xi.zone.CARPENTERS_LANDING and
|
|
prevZone == xi.zone.PHANAUET_CHANNEL
|
|
then
|
|
-- Zoning into Carpenter's Landing. Play the cs saved when we started the ride.
|
|
local bargeDestinationId = player:getCharVar('[barge]destinationDockId')
|
|
player:setCharVar('[barge]destinationDockId', 0)
|
|
|
|
-- get destinationData with failback to destinations.CENTRAL_LANDING in case of mangled data or route == destinations.CENTRAL_LANDING_EMFEA
|
|
local bargeDestinationData = dockEventData[bargeDestinationId] or dockEventData[destinations.CENTRAL_LANDING]
|
|
player:setPos(bargeDestinationData.arrivalPos)
|
|
|
|
return { bargeDestinationData.arrivalCsId, -1, bit.bor(xi.cutsceneFlag.UNKNOWN_1, xi.cutsceneFlag.NO_PCS) }
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
xi.barge.onTransportEvent = function(player, zoneId, transportId)
|
|
local aboard = player:getLocalVar('[barge]aboard')
|
|
local destData = nil
|
|
|
|
for _, bargeDestinationData in pairs(dockEventData) do
|
|
if bargeDestinationData.triggerAreaId == aboard then
|
|
destData = bargeDestinationData
|
|
|
|
break
|
|
end
|
|
end
|
|
|
|
if not destData then -- was not in trigger area for the transport event
|
|
return -1
|
|
end
|
|
|
|
if not utils.contains(transportId, destData.transports) then
|
|
-- Normal game client won't let you enter the boat trigger area unless the boat is there, but check this transport event aligns with the schedule to avoid shenanigans
|
|
|
|
-- was in trigger area but no in-service boat was departing from this dock
|
|
player:startEvent(destData.kickEvent)
|
|
elseif player:hasKeyItem(xi.ki.BARGE_TICKET) then
|
|
-- This is technically done on event end but does not matter
|
|
player:delKeyItem(xi.ki.BARGE_TICKET)
|
|
|
|
player:startEvent(destData.departEvent,
|
|
{
|
|
[0] = 0,
|
|
[1] = xi.ki.BARGE_TICKET,
|
|
[2] = 0, -- Important to be set to 0
|
|
isHidden = true,
|
|
flags = bit.bor(
|
|
xi.cutsceneFlag.UNKNOWN_1,
|
|
xi.cutsceneFlag.NO_PCS,
|
|
xi.cutsceneFlag.UNKNOWN_4,
|
|
xi.cutsceneFlag.UNKNOWN_7
|
|
),
|
|
})
|
|
elseif player:hasKeyItem(xi.ki.BARGE_MULTI_TICKET) then
|
|
local usesLeft = player:getCharVar('[barge]multiTicket') - 1
|
|
|
|
if usesLeft <= 0 then
|
|
usesLeft = 0
|
|
player:delKeyItem(xi.ki.BARGE_MULTI_TICKET)
|
|
end
|
|
|
|
player:setCharVar('[barge]multiTicket', usesLeft)
|
|
-- was in trigger area and had a ticket
|
|
player:startEvent(destData.departEvent,
|
|
{
|
|
[0] = usesLeft, -- Not actually used by CS but passed in
|
|
[1] = xi.ki.BARGE_MULTI_TICKET,
|
|
[2] = usesLeft + 1, -- This expects the number of uses before it get decremented
|
|
isHidden = true,
|
|
flags = bit.bor(
|
|
xi.cutsceneFlag.UNKNOWN_1,
|
|
xi.cutsceneFlag.NO_PCS,
|
|
xi.cutsceneFlag.UNKNOWN_4,
|
|
xi.cutsceneFlag.UNKNOWN_7
|
|
),
|
|
})
|
|
else
|
|
-- was in trigger area but didn't have a ticket
|
|
player:startEvent(destData.kickEvent)
|
|
end
|
|
end
|
|
|
|
-- index is the event option from menu
|
|
local tickets =
|
|
{
|
|
[1] =
|
|
{
|
|
keyItem = xi.ki.BARGE_TICKET,
|
|
cost = 50,
|
|
},
|
|
|
|
[2] =
|
|
{
|
|
keyItem = xi.ki.BARGE_MULTI_TICKET,
|
|
cost = 300,
|
|
charges = 10,
|
|
},
|
|
}
|
|
|
|
xi.barge.onTicketShopTrigger = function(player, eventId)
|
|
local hasKeyItemParam = 0
|
|
local numberTicket = player:getCharVar('[barge]multiTicket')
|
|
for i, ticketData in pairs(tickets) do
|
|
hasKeyItemParam = utils.mask.setBit(hasKeyItemParam, i - 1, player:hasKeyItem(ticketData.keyItem))
|
|
end
|
|
|
|
-- Params (KI1, KI2, Price of KI1, Price of KI2, Multiticket #s left, Which tickets does player have)
|
|
player:startEvent(eventId, tickets[1].keyItem, tickets[2].keyItem, tickets[1].cost, tickets[2].cost, numberTicket, hasKeyItemParam, 0, 0)
|
|
end
|
|
|
|
xi.barge.onTicketShopEventFinish = function(player, csid, option, npc)
|
|
local ID = zones[player:getZoneID()]
|
|
local numberTicket = player:getCharVar('[barge]multiTicket')
|
|
local ticketData = tickets[option]
|
|
|
|
if
|
|
ticketData and
|
|
(csid == 31 or
|
|
csid == 32 or
|
|
csid == 43)
|
|
then
|
|
local gil = player:getGil()
|
|
-- Event auto plays the correct message if you have the KI (and multi at max charges)
|
|
if
|
|
not player:hasKeyItem(ticketData.keyItem) or
|
|
(ticketData.charges and numberTicket < ticketData.charges)
|
|
then
|
|
if gil >= ticketData.cost then
|
|
player:delGil(ticketData.cost)
|
|
player:addKeyItem(ticketData.keyItem)
|
|
player:messageSpecial(ID.text.KEYITEM_OBTAINED, ticketData.keyItem, ticketData.charges or 0)
|
|
if ticketData.charges then
|
|
player:setCharVar('[barge]multiTicket', ticketData.charges)
|
|
end
|
|
else
|
|
-- TODO find out the cs params to auto-detect not enough gil to avoid incorrect messaging
|
|
-- the cs can automatically detect if the player doesn't have enough gil when choosing one to buy (passing no key item shows that): !cs 32 0 0 30 300
|
|
local showName = true
|
|
local turnToPlayer = false
|
|
-- dynamically addresses based on gender, neat!
|
|
player:showText(npc, ID.text.TOO_POOR, 0, 0, 0, 0, showName, turnToPlayer)
|
|
end
|
|
end
|
|
end
|
|
end
|