1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-23 13:17:45 +00:00

Merged in CuriousJorge/ffxiv-classic-server/develop (pull request #49)

Inventory fixes + Scripts added

Approved-by: Filip Maj <filipmaj@gmail.com>
This commit is contained in:
CuriousJorge 2017-10-10 14:14:08 +00:00 committed by Filip Maj
commit 4323eb5385
20 changed files with 1516 additions and 344 deletions

View file

@ -94,7 +94,30 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
return null; return null;
} }
public INV_ERROR AddItem(uint itemId)
public int GetItemQuantity(uint itemId)
{
return GetItemQuantity(itemId, 1);
}
public int GetItemQuantity(uint itemId, uint quality)
{
int count = 0;
for (int i = endOfListIndex - 1; i >= 0; i--)
{
InventoryItem item = list[i];
if (item.itemId == itemId && item.quality == quality)
count += item.quantity;
}
return count;
}
public int AddItem(uint itemId)
{ {
return AddItem(itemId, 1, 1); return AddItem(itemId, 1, 1);
} }
@ -105,22 +128,22 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
AddItem(itemId[i]); AddItem(itemId[i]);
} }
public INV_ERROR AddItem(uint itemId, int quantity) public int AddItem(uint itemId, int quantity)
{ {
return AddItem(itemId, quantity, 1); return AddItem(itemId, quantity, 1);
} }
public INV_ERROR AddItem(uint itemId, int quantity, byte quality) public int AddItem(uint itemId, int quantity, byte quality)
{ {
if (!IsSpaceForAdd(itemId, quantity, quality)) if (!IsSpaceForAdd(itemId, quantity, quality))
return INV_ERROR.INVENTORY_FULL; return (int)INV_ERROR.INVENTORY_FULL;
ItemData gItem = Server.GetItemGamedata(itemId); ItemData gItem = Server.GetItemGamedata(itemId);
if (gItem == null) if (gItem == null)
{ {
Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId);
return INV_ERROR.SYSTEM_ERROR; return (int)INV_ERROR.SYSTEM_ERROR;
} }
//Check if item id exists //Check if item id exists
@ -146,8 +169,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
} }
//If it's unique, abort //If it's unique, abort
if (quantityCount > 0 && gItem.isExclusive) if (HasItem(itemId) && gItem.isRare)
return INV_ERROR.ALREADY_HAS_UNIQUE; return (int)INV_ERROR.ALREADY_HAS_UNIQUE;
//New item that spilled over //New item that spilled over
while (quantityCount > 0) while (quantityCount > 0)
@ -163,7 +186,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
SendUpdatePackets(); SendUpdatePackets();
return INV_ERROR.SUCCESS; return (int)INV_ERROR.SUCCESS;
} }
public void RemoveItem(uint itemId) public void RemoveItem(uint itemId)

View file

@ -25,6 +25,7 @@ Actorclass Id - 1500295 : Lalaroon, Ul'dah
--]] --]]
require ("global") require ("global")
require ("shop")
shopInfo = { -- [ index ] = { itemId, gilPrice, sealPrice, city, itemCategory } shopInfo = { -- [ index ] = { itemId, gilPrice, sealPrice, city, itemCategory }
[1001] = {3020202, 100, 10000, 1, 1}, [1001] = {3020202, 100, 10000, 1, 1},
@ -121,7 +122,7 @@ function processGilShop(player)
location = INVENTORY_NORMAL; location = INVENTORY_NORMAL;
end end
purchaseItem(player, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][3], gilCurrency, location); purchaseItem(player, location, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][3], gilCurrency);
end end
end end
end end
@ -150,44 +151,9 @@ function processSealShop(player)
location = INVENTORY_NORMAL; location = INVENTORY_NORMAL;
end end
purchaseItem(player, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][2], playerGCSeal, location); purchaseItem(player, location, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][2], playerGCSeal);
end end
end end
end end
end end
function purchaseItem(player, itemId, quantity, quality, price, currency, location)
local worldMaster = GetWorldMaster();
local cost = quantity * price;
local gItemData = GetItemGamedata(itemId);
local isUnique = gItemData.isRare;
if player:GetInventory(location):HasItem(itemId) and isUnique then
-- You cannot have more than one <itemId> <quality> in your possession at any given time.
player:SendGameMessage(player, worldMaster, 40279, MESSAGE_TYPE_SYSTEM, itemId, quality);
return;
end
if (not player:GetInventory(location):IsFull() or player:GetInventory(location):IsSpaceForAdd(itemId, quantity)) then
if player:GetInventory(INVENTORY_CURRENCY):HasItem(currency, cost) then
player:GetInventory(INVENTORY_CURRENCY):removeItem(currency, cost)
player:GetInventory(location):AddItem(itemId, quantity, quality);
if currency == 1000001 then
-- You purchase <quantity> <itemId> <quality> for <cost> gil.
player:SendGameMessage(player, worldMaster, 25061, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, cost);
elseif currency == 1000201 or currency == 1000202 or currency == 1000203 then
-- You exchange <quantity> <GC seals> for <quantity> <itemId> <quality>.
player:SendGameMessage(player, GetWorldMaster(), 25275, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, price, player.gcCurrent);
end
else
-- You do not have enough gil. (Should never see this aside from packet injection, since client prevents buying if not enough currency)
player:SendGameMessage(player, worldMaster, 25065, MESSAGE_TYPE_SYSTEM);
end
else
-- Your inventory is full.
player:SendGameMessage(player, worldMaster, 60022, MESSAGE_TYPE_SYSTEM);
end
return
end

View file

@ -0,0 +1,43 @@
--[[
PopulaceCompanyBuffer Script
Functions:
eventTalkWelcome(player, boolean) - Welcome dialog. Boolean seems to be related to rank?
eventTalkBufEffect() - Dialog for applying Sanction
eventTalkBufEffectAfter(player) - Dialog after applying Sanction
eventTalkStepBreak() - Returns to NPC's neutral state
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
local gcRep = {
[1500388] = 1, -- Maelstrom Representative
[1500389] = 2, -- Adder Representative
[1500390] = 3, -- Flame Representative
}
function onEventStarted(player, npc, triggerName)
local playerGC = player.gcCurrent;
local playerGCRanks = {player.gcRankLimsa, player.gcRankGridania, player.gcRankUldah};
local choice = callClientFunction(player, "eventTalkWelcome", player, true);
if (choice == 1 and playerGCRanks[playerGC] > 10 and playerGCRanks[playerGC] < 112) then
callClientFunction(player, "eventTalkBufEffect");
callClientFunction(player, "eventTalkBufEffectAfter", player);
-- TODO: Add Sanction buff
else
player:SendMessage(0x20, "", "Quit hex editing your memory.");
end
callClientFunction(player, "eventTalkStepBreak");
player:endEvent();
end

View file

@ -0,0 +1,66 @@
--[[
PopulaceCompanyGLPublisher Script
xtx_gcRank for GC Rank values
Functions:
talkOutsider() - Dialog for no affiliated with GC. Seems to always read Maelstrom?
talkOfferWelcome(unk1) - Errors
askCompanyLeve() - Errors
askLeveDetail(unk1, unk2, unk3, unk4, unk5, unk6, unk7, unk8) - Errors
eventGLDifficulty() - Difficulty window, returns player choice
eventGLStart(leveName, difficulty, unk1) - leveName from xtx_guildleve
talkAfterOffer()
talkOfferLimit()
finishTalkTurn() - Resets NPC target/facing
eventGLPlay(leveName, guardianFavor, favorCost, difficulty) - Menu for active levequest
eventGLShinpu(guardianFavor, favorCost) - Menu to accept favor buff. evenGLPlay() calls it
eventGLThanks() - Errors
eventGLReward( -- Leve reward screen
guildleveId,
clearTime,
missionBonus,
difficultyBonus,
factionNumber,
factionBonus,
factionCredit,
glRewardItem,
glRewardNumber,
glRewardSubItem,
glRewardSubNumber,
difficulty
)
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
gcOfficer = {
[1500222] = 1, -- Storm Sergeant Hammil
[1500223] = 1, -- Storm Sergeant Sternn
[1500224] = 2, -- Serpent Sergeant Cordwyk
[1500225] = 2, -- Serpent Sergeant Lodall
[1500226] = 3, -- Flame Sergeant Byrne
[1500227] = 3, -- Flame Sergeant Dalvag
}
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "talkOutsider");
callClientFunction(player, "finishTalkTurn");
player:endEvent();
end

View file

@ -0,0 +1,45 @@
--[[
PopulaceCompanyGuide Script
Functions:
eventTalkWelcome() - Dialog for new recruits
eventTalkProvisional() - Message for when rank isn't high enough?
eventTalkExclusive() - Message for wrong GC.
eventTalkComMember(nil, npc, isFoundationDay) - Information menus for various GC related activities
eventTalkStepBreak() - Returns to NPC's neutral state
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
local gcRep = {
[1001737] = 1, -- Maelstrom Representative
[1001738] = 2, -- Adder Representative
[1001739] = 3, -- Flame Representative
}
function onEventStarted(player, npc, triggerName)
local playerGC = player.gcCurrent;
local playerGCRanks = {player.gcRankLimsa, player.gcRankGridania, player.gcRankUldah};
local npcGC = gcRep[npc:GetActorClassId()];
if (playerGC ~= npcGC and playerGCRanks[playerGC] == 127) then
callClientFunction(player, "eventTalkWelcome");
elseif (playerGC == npcGC and playerGCRanks[playerGC] == 127) then
callClientFunction(player, "eventTalkProvisional");
elseif (playerGC ~= npcGC and playerGCRanks[playerGC] ~= 127) then
callClientFunction(player, "eventTalkExclusive");
elseif (playerGC == npcGC and playerGCRanks[playerGC] > 10 and playerGCRanks[playerGC] < 112) then
callClientFunction(player, "eventTalkComMember", nil, npc, true);
end
callClientFunction(player, "eventTalkStepBreak");
player:endEvent();
end

View file

@ -33,6 +33,7 @@ eventTalkStepBreak() -- Returns NPC to their starting direction
--]] --]]
require ("global") require ("global")
require ("shop")
function init(npc) function init(npc)
return false, false, 0, 0; return false, false, 0, 0;
@ -44,7 +45,7 @@ gcOfficer = {
[1500201] = 3, -- Flame Shop [1500201] = 3, -- Flame Shop
} }
shopInfo = { -- [index] = { itemID, itemQuality, itemQuantity, itemCost gcRank, city, special, itemCategory } shopInfo = { -- [index] = { itemID, itemQuality, itemQuantity, itemCost, gcRank, city, special, itemCategory }
[100001] = {3010403, 1, 10, 20, 0, 1, 0, 1}, [100001] = {3010403, 1, 10, 20, 0, 1, 0, 1},
[100002] = {3010402, 1, 10, 30, 0, 1, 0, 1}, [100002] = {3010402, 1, 10, 30, 0, 1, 0, 1},
[100003] = {3020202, 1, 1, 50, 0, 1, 0, 1}, [100003] = {3020202, 1, 1, 50, 0, 1, 0, 1},
@ -450,7 +451,7 @@ shopInfo = { -- [index] = { itemID, itemQuality, itemQuantity, itemCost gcRank,
} }
function onEventStarted(player, npc, triggerName) function onEventStarted(player, npc, triggerName)
skipGCcheck = 1; -- 0 No, 1 Yes skipGCcheck = 0; -- 0 No, 1 Yes
playerGC = player.gcCurrent; playerGC = player.gcCurrent;
playerGCSeal = 1000200 + playerGC; playerGCSeal = 1000200 + playerGC;
playerCurrentRank = 13; playerCurrentRank = 13;
@ -470,7 +471,7 @@ function onEventStarted(player, npc, triggerName)
--player:SendMessage(0x20, "", "eventShopMenuOpen: " .. tostring(t1) .. ", ".. tostring(t2) .. ", ".. tostring(t3)); --player:SendMessage(0x20, "", "eventShopMenuOpen: " .. tostring(t1) .. ", ".. tostring(t2) .. ", ".. tostring(t3));
while (true) do while (true) do
-- TODO: ADD RANK CHECK, CITY CHECK, AND RANGE CHECK -- TODO: ADD RANK CHECK, CITY CHECK, AND ITEM-RANGE CHECK
buyResult, buyIndex = callClientFunction(player, "eventShopMenuAsk"); buyResult, buyIndex = callClientFunction(player, "eventShopMenuAsk");
@ -486,7 +487,7 @@ function onEventStarted(player, npc, triggerName)
end end
end end
purchaseItem(player, shopInfo[buyIndex][1], shopInfo[buyIndex][3], shopInfo[buyIndex][2], shopInfo[buyIndex][4], playerGCSeal, location); purchaseItem(player, location, shopInfo[buyIndex][1], shopInfo[buyIndex][3], shopInfo[buyIndex][2], shopInfo[buyIndex][4], playerGCSeal);
end end
--player:SendMessage(0x20, "", "Player picked an item at gcSealShopIndex " .. tostring(buyResult) .. ", ".. tostring(buyIndex)); --player:SendMessage(0x20, "", "Player picked an item at gcSealShopIndex " .. tostring(buyResult) .. ", ".. tostring(buyIndex));
@ -503,43 +504,6 @@ function onEventStarted(player, npc, triggerName)
end end
function purchaseItem(player, itemId, quantity, quality, price, currency, location)
local worldMaster = GetWorldMaster();
local cost = quantity * price;
local gItemData = GetItemGamedata(itemId);
local isUnique = gItemData.isRare;
if player:GetInventory(location):HasItem(itemId) and isUnique then
-- You cannot have more than one <itemId> <quality> in your possession at any given time.
player:SendGameMessage(player, worldMaster, 40279, MESSAGE_TYPE_SYSTEM, itemId, quality);
return;
end
if (not player:GetInventory(location):IsFull() or player:GetInventory(location):IsSpaceForAdd(itemId, quantity)) then
if player:GetInventory(INVENTORY_CURRENCY):HasItem(currency, cost) then
player:GetInventory(INVENTORY_CURRENCY):removeItem(currency, cost)
player:GetInventory(location):AddItem(itemId, quantity, quality);
if currency == 1000001 then
-- You purchase <quantity> <itemId> <quality> for <cost> gil.
player:SendGameMessage(player, worldMaster, 25061, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, cost);
elseif currency == 1000201 or currency == 1000202 or currency == 1000203 then
-- You exchange <quantity> <GC seals> for <quantity> <itemId> <quality>.
player:SendGameMessage(player, GetWorldMaster(), 25275, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, price, player.gcCurrent);
end
else
-- You do not have enough gil. (Should never see this aside from packet injection, since client prevents buying if not enough currency)
player:SendGameMessage(player, worldMaster, 25065, MESSAGE_TYPE_SYSTEM);
end
else
-- Your inventory is full.
player:SendGameMessage(player, worldMaster, 60022, MESSAGE_TYPE_SYSTEM);
end
return
end

View file

@ -0,0 +1,464 @@
--[[
PopulaceCompanySupply Script
This class handles the menus for player's delivering specific items in exchange for grand company seals.
The supply/provision schedule runs on a weekly rotation, which resets Monday at 12AM JST, with eight rotations total to cycle through.
Each desired item has a server-wide max that it can be turned in, and when that is fulfilled, it moves to the next item in that week's list to work on.
NPCs involved in the script use the Noc001 script for dialog and menu interactions.
Functions:
eventTalkPreJoin() - Dialog when you're not affiliated
eventTalkExclusive() - Dialog when you're part of a GC but not the one of the actor?
eventTalkJoined() - Salutes then softlocks the client due to removed dialog strings. Obsolete function.
eventQuestItemMenuOpen(itemId, itemPrice, itemPriceHq, supplyType) - supplyType: 1 = Supply, 2 = Provisioning, 3 = Totorak, 4 = Dzmael, 5 = Primal, 6 = NM drops
eventQuestItemMenuSelect(quantity, quality, unk) - Brings up the shop-style menu for viewing item detail and confirming item delivery. Args appear to do nothing on client?
eventQuestItemMenuClose() - Closes menu
eventQuestSupplyItemActor(unk1) -- Client calls this automatically for setting up Expeditionary window in some manner
eventQuestSupplyItemID(unk1, unk2) -- eventQuestSupplyItemActor() calls this to sets item ranges based on category
getEventQuestSupplyMode() - Returns current supply mode set by eventQuestItemMenuOpen()
eventTalkStepBreak() - Resets actor engage state
Noc001 Functions:
pENPCAskSupplyWelcome(npcGC) -- Welcome dialog
pENPCAskSupply(npcGC) -- Brings up the delivery selection menu
eventQuestAskExWelcome(npcGC) -- Dialog when you pick Expeditionary
eventQuestAskExArea(npcGC) -- Brings up the Expeditionary selection menu
pENPCAskNowTalk(npcGC) -- Dialog for picking Delivery Status from pENPCAskSupply()
nowSup(itemId1, current1, max1, itemId2, current2, max2, itemId3, current3, max3) -- Says current 3 items and current amount delivered vs. max it'll take
nowSupAddItem(itemId, current, max) -- Lists bonus item
pItem(itemId1, unk1, itemId2, unk2, itemId3, unk3, itemId4, unk4) -- Lists which item(s) you want to delivery. Fourth item is the bonus, set 0 for hidden.
showSupplyLimit(minutes, seconds, current, required) -- Shows time remaining to finish delivery, shows current/required amount
eventShowPrizeMessage(npcGC) -- Reward dialog for handing something in?
pELimitErr() -- Error msg for GC no longer accepting items.
pETradeErr() -- Transaction error. Inventory error?
pETradeErrLimit(minutes, seconds, current, required) -- Transaction error. Shows time remaining and current/required amount
pESuppylMaxErrKeyWait(isShowLimit, minutes, seconds, current, required) -- Error msg for delivery quota already filled. Optional timer/amount display
pESuppylSealMaxErr() -- Error msg for capped on GC seals, transaction incomplete
eventQuestCantEx(npcGC) -- Dialog explaining you need to be Private Second Class to do Expeditionary missions
--]]
require ("global")
require ("shop")
function init(npc)
return false, false, 0, 0;
end
local gcRep = {
[1500210] = 1, -- Maelstrom Representative
[1500211] = 2, -- Adder Representative
[1500212] = 3, -- Flame Representative
}
local gcItems = { -- Debug purposes. Static item list with seal value and max turn-in.
[111] = {id = 10002015, seals = 8, cap = 1900},
[112] = {id = 8031419, seals = 68, cap = 300},
[113] = {id = 3010011, seals = 3, cap = 5000},
[114] = {id = 8011108, seals = 89, cap = 400},
[115] = {id = 10004001, seals = 5, cap = 3000},
[116] = {id = 10008109, seals = 3, cap = 5000},
[117] = {id = 12000180, seals = 5, cap = 3000},
[118] = {id = 10004026, seals = 9, cap = 3400},
[121] = {id = 10008211, seals = 5, cap = 3000},
[122] = {id = 3020407, seals = 5, cap = 2500},
[123] = {id = 8030220, seals = 92, cap = 200},
[124] = {id = 8030922, seals = 99, cap = 400},
[125] = {id = 10001014, seals = 3, cap = 5000},
[126] = {id = 10008007, seals = 5, cap = 3000},
[127] = {id = 3011217, seals = 3, cap = 5000},
[128] = {id = 3011207, seals = 3, cap = 6000},
[131] = {id = 4030204, seals = 69, cap = 300},
[132] = {id = 10004103, seals = 9, cap = 1700},
[133] = {id = 10009208, seals = 6, cap = 3000},
[134] = {id = 1, seals = 1, cap = 1}, -- Unknown
[135] = {id = 10004008, seals = 9, cap = 1700},
[136] = {id = 10008007, seals = 5, cap = 3000},
[137] = {id = 3011201, seals = 5, cap = 3000},
[138] = {id = 10009401, seals = 6, cap = 6000},
[211] = {id = 10002012, seals = 5, cap = 3000},
[212] = {id = 4100007, seals = 51, cap = 300},
[213] = {id = 3010108, seals = 2, cap = 3000},
[214] = {id = 8080825, seals = 42, cap = 800},
[215] = {id = 10004003, seals = 5, cap = 3000},
[216] = {id = 10002012, seals = 3, cap = 5000},
[217] = {id = 3011104, seals = 2, cap = 3000},
[218] = {id = 3011107, seals = 3, cap = 6000},
}
local gcWeek = { -- Debug purposes. Static weekly item lists. [week] = { [city] = {[category] = { info } } }
[1] = {
[1] = { -- Limsa
[1] = { -- Supply
gcItems[111],
gcItems[112],
gcItems[113],
gcItems[114],
},
[2] = { -- Provision
gcItems[115],
gcItems[116],
gcItems[117],
gcItems[118],
}
},
[2] = { -- Gridania
[1] = { -- Supply
gcItems[121],
gcItems[122],
gcItems[123],
gcItems[124],
},
[2] = { -- Provision
gcItems[125],
gcItems[126],
gcItems[127],
gcItems[128],
}
},
[3] = { -- Ul'dah
[1] = { -- Supply
gcItems[131],
gcItems[132],
gcItems[133],
gcItems[134],
},
[2] = { -- Provision
gcItems[135],
gcItems[136],
gcItems[137],
gcItems[138],
}
}
},
[2] = {
[1] = { -- Limsa
[1] = { -- Supply
gcItems[211],
gcItems[212],
gcItems[213],
gcItems[214],
},
[2] = { -- Provision
gcItems[215],
gcItems[216],
gcItems[217],
gcItems[218],
}
}
}
}
local gcDelivery = { -- Debug purposes. Holds values for current turned in amount and 4th item bonus status.
week = 1,
currentCount = {
{
{49, 81, 5000, 5}, {2402, 4779, 589, 2} -- Limsa Supply/Provision
},
{
{1, 2, 3, 4}, {5, 6, 7, 8} -- Gridania Supply/Provision
},
{
{10, 32, 9, 18}, {23, 49, 9, 300} -- Ul'dah Supply/Provision
}
},
bonus = { {1, 1}, {0,1}, {0,1} }; -- City -> {Supply, Provision}
timeRemainingMinutes = 99,
timeRemainingSeconds = 59,
}
local supplyQuest = GetStaticActor("Noc001");
local skipGCcheck = false; -- Debug
local skipRankCheck = false; -- Debug
local gcCheckProceed = false; -- Debug
function onEventStarted(player, npc, triggerName)
local playerGC = player.gcCurrent;
local limsaRank = player.gcRankLimsa;
local gridaniaRank = player.gcRankGridania;
local uldahRank = player.gcRankUldah;
local playerGCSeal = 1000200 + playerGC;
local npcId = npc:GetActorClassId();
local npcGC = gcRep[npcId];
if (skipGCcheck == true) then
gcCheckProceed = true;
end
if ((playerGC ~= npcGC) and skipGCcheck == false) then
if (playerGC == 0) then
callClientFunction(player, "eventTalkPreJoin");
else
callClientFunction(player, "eventTalkExclusive");
end
else
gcCheckProceed = true;
end
if gcCheckProceed then
callClientFunction(player, "delegateEvent", player, supplyQuest, "pENPCAskSupplyWelcome", gcRep[npcId]);
while (true) do
local choice = callClientFunction(player, "delegateEvent", player, supplyQuest, "pENPCAskSupply", gcRep[npcId]);
if (choice == 2) then -- Supply
deliveryMenuInfo(player, npcGC, 1);
elseif (choice == 3) then -- Provision
deliveryMenuInfo(player, npcGC, 2);
elseif (choice == 4) then -- Expeditionary
local proceed = false;
if (skipRankCheck == true) then
proceed = true;
else
if (playerGC == 1 and limsaRank >= 13 and limsaRank <= 111)
or (playerGC == 2 and gridaniaRank >= 13 and gridaniaRank <= 111)
or (playerGC == 3 and uldahRank >= 13 and uldahRank <= 111) then
proceed = true
end
end
if proceed == true then
callClientFunction(player, "delegateEvent", player, supplyQuest, "eventQuestAskExWelcome", gcRep[npcId]);
while (true) do
local exChoice = callClientFunction(player, "delegateEvent", player, supplyQuest, "eventQuestAskExArea", gcRep[npcId]);
if (exChoice >= 3) then
deliveryMenuOpen(player, npc, 0,0,0, exChoice);
else
break;
end
end
else
callClientFunction(player, "delegateEvent", player, supplyQuest, "eventQuestCantEx",gcRep[npcId]);
end
elseif (choice == 5) then -- Requested item
deliveryStatus(player, npcGC);
else
break;
end
wait(1);
end
end
callClientFunction(player, "eventTalkStepBreak");
player:endEvent()
end
function deliveryMenuInfo(player, city, category)
local gcContents = getWeeklyItems(city, category);
local gcCurrent = getCurrentCount(city, category);
local supplyChoice = 0;
while (true) do
if gcDelivery.bonus[city][category] == 1 then -- Show fourth item if condition is met, otherwise show three.
supplyChoice = callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"pItem",
gcContents[1].id,
1,
gcContents[2].id,
1,
gcContents[3].id,
1,
gcContents[4].id,
1
);
else
supplyChoice = callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"pItem",
gcContents[1].id,
1,
gcContents[2].id,
1,
gcContents[3].id,
1,
0,
0
);
end
if supplyChoice >= 2 then
if gcCurrent[supplyChoice-1] < gcContents[supplyChoice-1].cap then
local hqPrice = math.ceil(gcContents[supplyChoice-1].seals * 1.5);
deliveryMenuOpen
(
player,
npc,
gcContents[supplyChoice-1].id,
gcContents[supplyChoice-1].seals,
hqPrice,
category
);
else
callClientFunction(player, "delegateEvent", player, supplyQuest, "pESuppylMaxErrKeyWait");
end
elseif supplyChoice == 1 then
break;
end
wait(1);
end
end
function deliveryMenuOpen(player, npc, itemId, price, hqPrice, supplyType)
callClientFunction(player, "eventQuestItemMenuOpen", itemId, price, hqPrice, supplyType);
while (true) do
local choice, quantity, quality, itemSlot, Type7Param = callClientFunction(player, "eventQuestItemMenuSelect");
if choice == false then
callClientFunction(player, "eventQuestItemMenuClose");
break;
end
--[[
player:SendMessage(0x20, "", "Choice: " .. tostring(choice));
player:SendMessage(0x20, "", "Quantity: " .. tostring(quantity));
player:SendMessage(0x20, "", "Quality: " .. tostring(quality));
player:SendMessage(0x20, "", "Slot: " .. tostring(itemSlot)); -- Broke at some point, always return 0, investigate sometime
player:SendMessage(0x20, "", "Type7Param: " .. tostring(Type7Param.slot));
--]]
pickedItem = GetItemGamedata(player:GetInventory(INVENTORY_NORMAL):GetItemAtSlot(Type7Param.slot).itemId).name;
player:SendMessage(0x20, "", "Player tried to deliver " .. quantity .. " " .. pickedItem);
-- TODO: Add error handling for capped seals, no-long-available-to-deliver, etc
wait(1);
end
end
function deliveryStatus(player, city)
local gcContents = getWeeklyItems(city, 1);
local gcCurrent = getCurrentCount(city, 1);
callClientFunction(player, "delegateEvent", player, supplyQuest, "pENPCAskNowTalk", gcRep[npcId]);
callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"nowSup",
gcContents[1].id,
gcCurrent[1],
gcContents[1].cap,
gcContents[2].id,
gcCurrent[2],
gcContents[2].cap,
gcContents[3].id,
gcCurrent[3],
gcContents[3].cap
);
if gcDelivery.bonus[city][1] == 1 then
callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"nowSupAddItem",
gcContents[4].id,
gcCurrent[4],
gcContents[4].cap
);
end;
gcContents = getWeeklyItems(city, 2);
gcCurrent = getCurrentCount(city, 2);
callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"nowSup",
gcContents[1].id,
gcCurrent[1],
gcContents[1].cap,
gcContents[2].id,
gcCurrent[2],
gcContents[2].cap,
gcContents[3].id,
gcCurrent[3],
gcContents[3].cap
);
if gcDelivery.bonus[city][2] == 1 then
callClientFunction
(
player,
"delegateEvent",
player,
supplyQuest,
"nowSupAddItem",
gcContents[4].id,
gcCurrent[4],
gcContents[4].cap
);
end;
callClientFunction(player, "delegateEvent", player, supplyQuest, "showSupplyLimit", gcDelivery.timeRemainingMinutes, gcDelivery.timeRemainingSeconds, 2, 8);
end
function getWeeklyItems(city, category)
return gcWeek[gcDelivery.week][city][category]
end
function getCurrentCount(city, category)
return gcDelivery.currentCount[city][category];
end

View file

@ -1,63 +1,108 @@
--[[
PopulaceGuildShop Script
In 1.20, the devs removed Guild Marks as acquirable. In 1.21, this class was set up to allow exchanging them for
a variety of materia/crystals/gil, as well as refunding traits purchased with marks. Traits used to be purchased
to slot in, where-as with late-XIV they are just automatically unlocked once the appropriate level is met.
Functions:
cashbackTalkCommand(arg1 through arg10) -- Dialog for refunding purchased skills prior to Job update. Args are xtx_command values for command names.
cashbackTalk(nil, refundAmount, arg3 through arg10) -- Dialog for refunding treaties to guild marks. Arg3 through 10 use xtx_itemName values.
selectMode(nil, npcId, isShowExchange, guildCurrency, unk) -- Menus for exchanging leftover marks, undoing class points, and learning about guild. Unk seems related to point resetting
maskShopListIndex(shopPack?, isSomething) -- Presumably hides an item in the shop list. Needs to be called after openShopBuy or errors client.
guildExplain(npcId, player) -- Guild Mark tutorial dialog. selectMode calls this on its own
--]]
require ("global") require ("global")
require ("shop")
function init(npc) function init(npc)
return false, false, 0, 0; return false, false, 0, 0;
end end
guildShopInfo = { -- [actor id] = { saySheetId, guildmarkCurrency }
[1000157] = {9, 1000103}, -- Marauder, S'raemha
[1000158] = {24, 1000120}, -- Culinarian, Noline
[1000162] = {18, 1000114}, -- Blacksmith, Qhas Chalahko
[1000164] = {16, 1000123}, -- Fishermen, Faucillien
[1000459] = {21, 1000117}, -- Leatherworker, Gallia
[1000460] = {13, 1000111}, -- Conjurer, Hetzkin
[1000461] = {15, 1000122}, -- Botanist, Kipopo
[1000462] = {11, 1000107}, -- Lancer, Clarembald
[1000464] = {10, 1000106}, -- Archer, Cassandra
[1000466] = {17, 1000113}, -- Carpenter, Frances
[1000631] = {8, 1000102}, -- Gladiator, Coynach
[1000632] = {7, 1000101}, -- Pugilist, Moruith
[1000633] = {12, 1000110}, -- Thaumaturge, Nyunoeya
[1000634] = {23, 1000119}, -- Alchemist, Kylene
[1000635] = {20, 1000116}, -- Goldsmith, Hnaufrid
[1000636] = {22, 1000118}, -- Weaver, Lafla Morfla
[1000637] = {14, 1000121}, -- Miner, Shilgen
[1001461] = {19, 1000115}, -- Armorer, Notrelchamps
}
function onEventStarted(player, npc) function onEventStarted(player, npc)
saySheetId = 1; local npcId = npc:GetActorClassId();
local saySheetId = guildShopInfo[npcId][1];
if (npc:GetActorClassId() == 1000157) then local shopCurrency = guildShopInfo[npcId][2];
saySheetId = 9; local gilCurrency = 1000001;
elseif (npc:GetActorClassId() == 1000158) then local keepersHymn = 3020410;
saySheetId = 24; local shopPack = 0;
elseif (npc:GetActorClassId() == 1000162) then
saySheetId = 18;
elseif (npc:GetActorClassId() == 1000164) then
saySheetId = 16;
elseif (npc:GetActorClassId() == 1000459) then
saySheetId = 21;
elseif (npc:GetActorClassId() == 1000460) then
saySheetId = 13;
elseif (npc:GetActorClassId() == 1000461) then
saySheetId = 15;
elseif (npc:GetActorClassId() == 1000462) then
saySheetId = 11;
elseif (npc:GetActorClassId() == 1000464) then
saySheetId = 10;
elseif (npc:GetActorClassId() == 1000466) then
saySheetId = 17;
elseif (npc:GetActorClassId() == 1000631) then
saySheetId = 8;
elseif (npc:GetActorClassId() == 1000632) then
saySheetId = 7;
elseif (npc:GetActorClassId() == 1000633) then
saySheetId = 12;
elseif (npc:GetActorClassId() == 1000634) then
saySheetId = 23;
elseif (npc:GetActorClassId() == 1000635) then
saySheetId = 20;
elseif (npc:GetActorClassId() == 1000636) then
saySheetId = 22;
elseif (npc:GetActorClassId() == 1000637) then
saySheetId = 14;
elseif (npc:GetActorClassId() == 1001461) then
saySheetId = 19;
end
callClientFunction(player, "welcomeTalk", nil, saySheetId, player); callClientFunction(player, "welcomeTalk", nil, saySheetId, player);
while (true) do while (true) do
choice = callClientFunction(player, "selectMode", nil, npc:GetActorClassId(), false, 1000001); --Step 2, state your business local choice = callClientFunction(player, "selectMode", nil, npcId, true, shopCurrency, 100);
if (choice == 3) then if (choice == 3) then -- Undo Point Allotment
-- TODO: Add point reset handling
elseif (choice == 4) then elseif (choice == 4) then -- Leave menu selected
player:EndEvent(); player:EndEvent();
break; break;
end elseif (choice == nil) then -- Escape key hit to leave menu
player:EndEvent();
break
elseif (choice >= 102 and choice <= 120) then -- Exchange marks for Materia
shopPack = choice + 18; -- Index offset
if (choice == 119) then
shopPack = shopPack + 1;
elseif (choice == 120) then -- Exchange marks for Crystals
shopPack = 144;
end;
processGuildShop(player, shopPack, shopCurrency);
elseif (choice == 121) then -- Exchange marks for Gil. 1 mark = 4 gil
local markAmount = player:GetInventory(INVENTORY_CURRENCY):GetItemQuantity(shopCurrency);
purchaseItem(player, INVENTORY_CURRENCY, gilCurrency, markAmount*4, 1, markAmount, shopCurrency);
end end
end
player:EndEvent()
end
function processGuildShop(player, choice, currency)
callClientFunction(player, "openShopBuy", player, choice, currency);
--callClientFunction(player, "maskShopListIndex", 137, true);
while (true) do
buyResult, quantity = callClientFunction(player, "selectShopBuy", player);
if (buyResult == 0) then
callClientFunction(player, "closeShopBuy", player);
break;
else
player:SendMessage(0x20, "", string.format("Player purchased %s item(s) at index %s in shopPack %s.", quantity, buyResult, choice));
end
end
end end

View file

@ -18,6 +18,8 @@ openShopSell(player) - Call this to open sell window
selectShopSell(player) - Call after openShopSell() selectShopSell(player) - Call after openShopSell()
closeShopSell(player) - Closes the sell window closeShopSell(player) - Closes the sell window
confirmSellingItem(itemId, quality, quantity, gil) - Simple Sell confirmation window
selectFacility(?, sheetId, 3) - Opens the facility chooser. selectFacility(?, sheetId, 3) - Opens the facility chooser.
confirmUseFacility(player, cost) - Facility cost confirm confirmUseFacility(player, cost) - Facility cost confirm
@ -30,6 +32,92 @@ finishTalkTurn() - Done at the end.
--]] --]]
require ("global") require ("global")
require ("shop")
shopInfo = { -- [actorclass id] = { welcomeText, shopMode, shopPack{s} }
[1000159] = {34, 0, 1016},
[1000163] = {49, 0, 1017},
[1000165] = {74, 0, 1019},
[1001458] = {44, 0, 1018},
[1500405] = {320, 0, 1013},
[1500407] = {321, 0, 1012},
[1500411] = {322, 0, 2017},
[1500414] = {324, 0, 1012},
[1500419] = {327, 0, 1012},
[1500422] = {332, 0, 1013},
[1500423] = {331, 0, 2017},
[1500429] = {328, 0, 2017},
[1500430] = {281, 0, 5121},
[1600001] = {6, 0, 1006},
[1600002] = {7, 0, 1007},
[1600003] = {8, 0, 1008},
[1600004] = {9, 0, 1009},
[1600005] = {10, 0, 1010},
[1600006] = {11, 0, 1011},
[1600007] = {12, 0, 1012},
[1600008] = {13, 0, 1013},
[1600009] = {14, 0, 1014},
[1600010] = {15, 0, 1015},
[1600011] = {1, 0, 1001},
[1600012] = {2, 0, 1002},
[1600013] = {3, 0, 1003},
[1600014] = {4, 0, 1004},
[1600016] = {5, 0, 1005},
[1600017] = {39, 0, 2020},
[1600018] = {59, 0, 2021},
[1600019] = {75, 0, 2022},
[1600020] = {77, 0, 2010},
[1600021] = {78, 0, 2011},
[1600022] = {79, 0, 2012},
[1600023] = {80, 0, 2013},
[1600024] = {81, 0, 2014},
[1600025] = {82, 0, 2015},
[1600026] = {83, 0, 2016},
[1600027] = {84, 0, 2017},
[1600028] = {85, 0, 2018},
[1600029] = {86, 0, 2019},
[1600030] = {87, 0, 2001},
[1600031] = {88, 0, 2003},
[1600032] = {89, 0, 2002},
[1600033] = {90, 0, 2004},
[1600034] = {91, 0, 2005},
[1600035] = {92, 0, 2006},
[1600036] = {93, 0, 2007},
[1600037] = {94, 0, 2008},
[1600039] = {69, 0, 3020},
[1600040] = {54, 0, 3019},
[1600041] = {64, 0, 3021},
[1600042] = {76, 0, 3022},
[1600043] = {96, 0, 3009},
[1600044] = {97, 0, 3010},
[1600045] = {98, 0, 3011},
[1600046] = {99, 0, 3012},
[1600047] = {100, 0, 3013},
[1600048] = {101, 0, 3014},
[1600049] = {102, 0, 3016},
[1600050] = {103, 0, 3015},
[1600051] = {104, 0, 3017},
[1600052] = {105, 0, 3004},
[1600053] = {106, 0, 3007},
[1600054] = {107, 0, 3018},
[1600055] = {108, 0, 3006},
[1600056] = {109, 0, 3005},
[1600057] = {110, 0, 3002},
[1600058] = {111, 0, 3003},
[1600059] = {112, 0, 3001},
[1600064] = {235, 0, 2023},
[1600066] = {237, 0, 3023},
[1600075] = {245, 1, {5021,5022,5023,5024,5025,5026} },
[1600076] = {247, 1, {5027,5028,5029,5030,5031,5032} },
[1600077] = {248, 1, {5033,5034,5035,5036,5037,5038} },
[1600080] = {251, 1, {5051,5052,5053,5054,5055,5056} },
[1600081] = {255, 1, {5075,5076,5077,5078,5079,5080} },
[1600089] = {260, 1, {5105,5106,5107,5108,5109,5110} },
[1600092] = {263, 0, 2024},
[1600094] = {265, 0, 3024},
[1600100] = {281, 2, {5001, 5002, 5007, 5008} },
}
function init(npc) function init(npc)
return false, false, 0, 0; return false, false, 0, 0;
@ -37,43 +125,64 @@ end
function onEventStarted(player, npc, triggerName) function onEventStarted(player, npc, triggerName)
require("/unique/".. npc.zone.zoneName .."/PopulaceShopSalesman/" .. npc:GetUniqueId()) -- require("/unique/".. npc.zone.zoneName .."/PopulaceShopSalesman/" .. npc:GetUniqueId())
npcId = npc:GetActorClassId();
if (shopInfo.shopCurrancy == nil) then if shopInfo[npcId] == nil then
shopInfo.shopCurrancy = 1000001; errorMsg = string.format("This PopulaceShopSalesman actor has no shop set. Actor Class Id: %s", npcId);
player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "", errorMsg );
player:EndEvent();
return;
end;
shopCurrancy = 1000001;
callClientFunction(player, "welcomeTalk", shopInfo[npcId][1], player);
if npcId == 1000159 then -- DoH Guild NPCs with Facility menu
tutorialId = 36;
elseif npcId == 1000163 then
tutorialId = 31;
elseif npcId == 1001458 then
tutorialId = 30;
elseif npcId == 1600017 then
tutorialId = 29;
elseif npcId == 1600018 then
tutorialId = 33;
elseif npcId == 1600039 then
tutorialId = 35;
elseif npcId == 1600040 then
tutorialId = 32;
elseif npcId == 1600041 then
tutorialId = 34;
else
tutorialId = -8;
end end
callClientFunction(player, "welcomeTalk", shopInfo.welcomeText, player);
while (true) do while (true) do
tutorialId = -8; if (shopInfo[npcId][2] == 0) then
if (shopInfo.tutorialId ~= nil) then
tutorialAskMode = shopInfo.tutorialId;
end
if (shopInfo.selectMode == nil or shopInfo.selectMode == 0) then
choice = callClientFunction(player, "selectMode", tutorialId); choice = callClientFunction(player, "selectMode", tutorialId);
elseif (shopInfo.selectMode == 1) then elseif (shopInfo[npcId][2] == 1) then
choice = callClientFunction(player, "selectModeOfClassVendor"); choice = callClientFunction(player, "selectModeOfClassVendor");
elseif (shopInfo.selectMode == 2) then elseif (shopInfo[npcId][2] == 2) then
choice = callClientFunction(player, "selectModeOfMultiWeaponVendor", tutorialId); choice = callClientFunction(player, "selectModeOfMultiWeaponVendor", tutorialId);
elseif (shopInfo.selectMode == 3) then elseif (shopInfo[npcId][2] == 3) then
choice = callClientFunction(player, "selectModeOfMultiArmorVendor", tutorialId); choice = callClientFunction(player, "selectModeOfMultiArmorVendor", tutorialId);
end end
if (choice == nil) then if (choice == nil or choice == -3) then
break; break;
end end
if (shopInfo.selectMode == nil or shopInfo.selectMode == 0) then if (shopInfo[npcId][2] == 0) then
processNormalShop(player, choice); processNormalShop(player, choice);
elseif (shopInfo.selectMode == 1) then elseif (shopInfo[npcId][2] == 1) then
processNormalShop(player, choice);
elseif (shopInfo.selectMode == 2) then
processMultiShop(player, choice); processMultiShop(player, choice);
elseif (shopInfo.selectMode == 3) then elseif (shopInfo[npcId][2] == 2) then
processMultiShop(player, choice);
elseif (shopInfo[npcId][2] == 3) then
processMultiShop(player, choice); processMultiShop(player, choice);
end end
@ -86,83 +195,96 @@ end
function processNormalShop(player, choice) function processNormalShop(player, choice)
if (choice == 1) then if (choice == 1) then
callClientFunction(player, "openShopBuy", player, shopInfo.shopPack, shopInfo.shopCurrancy); callClientFunction(player, "openShopBuy", player, shopInfo[npcId][3], shopCurrancy);
while (true) do while (true) do
buyResult, index, quantity = callClientFunction(player, "selectShopBuy", player); buyResult, quantity = callClientFunction(player, "selectShopBuy", player);
player:GetInventory(location):AddItem(3020308, 1);
if (buyResult == 0) then if (buyResult == 0) then
callClientFunction(player, "closeShopBuy", player); callClientFunction(player, "closeShopBuy", player);
break; break;
else else
player:SendMessage(0x20, "", "Player bought a thing at slot " .. tostring(buyResult).. " with quantity "..tostring(index).."."); -- purchaseItem(player, shopInfo.shopContents[buyResult].id, quantity, shopInfo.shopContents[buyResult].hq, shopInfo.shopContents[buyResult].gil, shopInfo.shopCurrancy);
end end
end end
elseif (choice == 2) then elseif (choice == 2) then
callClientFunction(player, "openShopSell", player); openSellMenu(player);
while (true) do
sellResult = callClientFunction(player, "selectShopSell", player);
if (sellResult == nil) then
callClientFunction(player, "closeShopSell", player);
break;
else
player:SendMessage(0x20, "", "Player sold a thing at slot " .. tostring(sellResult)..".");
itemToSell = player:GetInventory(0x00):GetItemAtSlot(sellResult.slot);
gItemTOSell = GetItemGamedata(itemToSell.itemId);
player:GetInventory(0x63):AddItem(shopInfo.shopCurrancy, gItemTOSell.sellPrice);
player:GetInventory(0x00):RemoveItemAtSlot(sellResult.slot);
end
end
elseif (choice == 3) then elseif (choice == 3) then
callClientFunction(player, "selectFacility", 2, 35, 3); local classFacility = (shopInfo[npcId][1] + 1) or 35;
callClientFunction(player, "confirmUseFacility", player, 35); facilityChoice = callClientFunction(player, "selectFacility", nil, classFacility, 3);
if facilityChoice == 1 then
callClientFunction(player, "confirmUseFacility", player, 200);
elseif facilityChoice == 2 then
callClientFunction(player, "confirmUseFacility", player, 400);
elseif facilityChoice == 3 then
callClientFunction(player, "confirmUseFacility", player, 1000);
end
elseif (choice == 4) then elseif (choice == 4) then
callClientFunction(player, "startTutorial", nil, shopInfo.classAskMode); callClientFunction(player, "startTutorial", nil, tutorialId);
end end
end end
function processMultiShop(player, choice, sellType) function processMultiShop(player, choice, sellType)
if (choice >= 1 and choice <= 4) then if (choice >= 1 and choice <= 6) then
callClientFunction(player, "openShopBuy", player, shopInfo.shopPack[choice], shopInfo.shopCurrancy); callClientFunction(player, "openShopBuy", player, shopInfo[npcId][3][choice], shopCurrancy);
while (true) do while (true) do
buyResult, index, quantity = callClientFunction(player, "selectShopBuy", player); buyResult, quantity = callClientFunction(player, "selectShopBuy", player);
player:GetInventory(location):AddItem(3020308, 1);
if (buyResult == 0) then if (buyResult == 0) then
callClientFunction(player, "closeShopBuy", player); callClientFunction(player, "closeShopBuy", player);
break; break;
else else
player:SendMessage(0x20, "", "Player bought a thing at slot " .. tostring(buyResult).."."); -- purchaseItem(player, shopInfo.shopContents[choice][buyResult].id, quantity, shopInfo.shopContents[choice][buyResult].hq, shopInfo.shopContents[choice][buyResult].gil, shopInfo.shopCurrancy);
end end
end end
elseif (choice == 0) then elseif (choice == 0) then
openSellMenu(player);
elseif (choice == 6) then
callClientFunction(player, "selectFacility", 2, 35, 3);
callClientFunction(player, "confirmUseFacility", player, 35);
elseif (choice == 7) then
callClientFunction(player, "startTutorial", nil, tutorialId);
end
end
function openSellMenu(player)
callClientFunction(player, "openShopSell", player); callClientFunction(player, "openShopSell", player);
while (true) do while (true) do
sellResult = callClientFunction(player, "selectShopSell", player); sellResult, sellQuantity, sellState, unknown, sellItemSlot = callClientFunction(player, "selectShopSell", player);
if (sellResult == nil) then if (sellResult == nil) then
callClientFunction(player, "closeShopSell", player); callClientFunction(player, "closeShopSell", player);
break; break;
else else
player:SendMessage(0x20, "", "Player sold a thing at slot " .. tostring(sellResult).."."); if sellState == 1 then
itemToSell = player:GetInventory(INVENTORY_NORMAL):GetItemAtSlot(sellItemSlot-1);
gItemSellId = itemToSell.itemId;
gItemQuality = itemToSell.quality;
gItemPrice = GetItemGamedata(gItemSellId);
gItemPrice = gItemPrice.sellPrice;
if gItemQuality == 2 then -- +1
gItemPrice = (math.floor(gItemPrice * 1.10));
elseif gItemQuality == 3 then -- +2
gItemPrice = (math.floor(gItemPrice * 1.25));
elseif gItemQuality == 4 then -- +3
gItemPrice = (math.floor(gItemPrice * 1.50));
end end
end callClientFunction(player, "informSellPrice", 1, sellItemSlot, gItemPrice);
elseif (choice == 6) then
callClientFunction(player, "selectFacility", 2, 35, 3);
callClientFunction(player, "confirmUseFacility", player, 35);
elseif (choice == 7) then
callClientFunction(player, "startTutorial", nil, shopInfo.classAskMode);
end
elseif sellState == nil then
sellItem(player, gItemSellId, sellQuantity, gItemQuality, gItemPrice, sellItemSlot-1, shopCurrancy);
end
end
end
end end

View file

@ -6,8 +6,8 @@ DiceCommand Script
function onEventStarted(player, actor, triggerName, maxNumber) function onEventStarted(player, actor, triggerName, maxNumber)
if (maxNumber == nil) then if (maxNumber == nil or maxNumber > 1000 or maxNumber < 1) then
maxNumber = 999; maxNumber = 100;
end end
result = math.random(0, maxNumber); result = math.random(0, maxNumber);

View file

@ -69,7 +69,7 @@ function onEventStarted(player, actor, triggerName, emoteId, unknownArg1, arg2,
targetId = 0; targetId = 0;
end end
if (player:GetState() == 0) then if (player:GetState() == 0 or player:GetState() == 11 or player:GetState() == 13) then
emote = emoteTable[emoteId]; emote = emoteTable[emoteId];
if (emote ~= nil) then if (emote ~= nil) then
player:doEmote(targetId, emote.animId, emote.descId); player:doEmote(targetId, emote.animId, emote.descId);

View file

@ -6,13 +6,99 @@ properties = {
description = description =
[[ [[
Adds currency <qty> to player or <targetname> Adds currency <qty> to player or <targetname>
!addcurrency <item> <qty> | Defaults to gil if no item entered
!addcurrency <item> <qty> <targetname> | !givecurrency <item> <qty> |
!givecurrency <item> <qty> <targetname> |
]], ]],
} }
function onTrigger(player, argc, currency, qty, name, lastName) currencyItems = {
["GIL"] = 1000001,
["FIRE_SHARD"] = 1000003,
["ICE_SHARD"] = 1000004,
["WIND_SHARD"] = 1000005,
["EARTH_SHARD"] = 1000006,
["LIGHTNING_SHARD"] = 1000007,
["WATER_SHARD"] = 1000008,
["FIRE_CRYSTAL"] = 1000009,
["ICE_CRYSTAL"] = 1000010,
["WIND_CRYSTAL"] = 1000011,
["EARTH_CRYSTAL"] = 1000012,
["LIGHTNING_CRYSTAL"] = 1000013,
["WATER_CRYSTAL"] = 1000014,
["FIRE_CLUSTER"] = 1000015,
["ICE_CLUSTER"] = 1000016,
["WIND_CLUSTER"] = 1000017,
["EARTH_CLUSTER"] = 1000018,
["LIGHTNING_CLUSTER"] = 1000019,
["WATER_CLUSTER"] = 1000020,
["PUGILISTS_GUILD_MARK"] = 1000101,
["GLADIATORS_GUILD_MARK"] = 1000102,
["MARAUDERS_GUILD_MARK"] = 1000103,
["ARCHERS_GUILD_MARK"] = 1000106,
["LANCERS_GUILD_MARK"] = 1000107,
["THAUMATURGES_GUILD_MARK"] = 1000110,
["CONJURERS_GUILD_MARK"] = 1000111,
["CARPENTERS_GUILD_MARK"] = 1000113,
["BLACKSMITHS_GUILD_MARK"] = 1000114,
["ARMORERS_GUILD_MARK"] = 1000115,
["GOLDSMITHS_GUILD_MARK"] = 1000116,
["LEATHERWORKERS_GUILD_MARK"] = 1000117,
["WEAVERS_GUILD_MARK"] = 1000118,
["ALCHEMISTS_GUILD_MARK"] = 1000119,
["CULINARIANS_GUILD_MARK"] = 1000120,
["MINERS_GUILD_MARK"] = 1000121,
["BOTANISTS_GUILD_MARK"] = 1000122,
["FISHERMENS_GUILD_MARK"] = 1000123,
["STORM_SEAL"] = 1000201,
["SERPENT_SEAL"] = 1000202,
["FLAME_SEAL"] = 1000203,
["FIRESHARD"] = 1000003,
["ICESHARD"] = 1000004,
["WINDSHARD"] = 1000005,
["EARTHSHARD"] = 1000006,
["LIGHTNINGSHARD"] = 1000007,
["WATERSHARD"] = 1000008,
["FIRECRYSTAL"] = 1000009,
["ICECRYSTAL"] = 1000010,
["WINDCRYSTAL"] = 1000011,
["EARTHCRYSTAL"] = 1000012,
["LIGHTNINGCRYSTAL"] = 1000013,
["WATERCRYSTAL"] = 1000014,
["FIRECLUSTER"] = 1000015,
["ICECLUSTER"] = 1000016,
["WINDCLUSTER"] = 1000017,
["EARTHCLUSTER"] = 1000018,
["LIGHTNINGCLUSTER"] = 1000019,
["WATERCLUSTER"] = 1000020,
["PUGILISTSGUILDMARK"] = 1000101,
["GLADIATORSGUILDMARK"] = 1000102,
["MARAUDERSGUILDMARK"] = 1000103,
["ARCHERSGUILDMARK"] = 1000106,
["LANCERSGUILDMARK"] = 1000107,
["THAUMATURGESGUILDMARK"] = 1000110,
["CONJURERSGUILDMARK"] = 1000111,
["CARPENTERSGUILDMARK"] = 1000113,
["BLACKSMITHSGUILDMARK"] = 1000114,
["ARMORERSGUILDMARK"] = 1000115,
["GOLDSMITHSGUILDMARK"] = 1000116,
["LEATHERWORKERSGUILDMARK"] = 1000117,
["WEAVERSGUILDMARK"] = 1000118,
["ALCHEMISTSGUILDMARK"] = 1000119,
["CULINARIANSGUILDMARK"] = 1000120,
["MINERSGUILDMARK"] = 1000121,
["BOTANISTSGUILDMARK"] = 1000122,
["FISHERMENSGUILDMARK"] = 1000123,
["STORMSEAL"] = 1000201,
["SERPENTSEAL"] = 1000202,
["FLAMESEAL"] = 1000203,
}
function onTrigger(player, argc, item, qty, name, lastName)
local sender = "[givecurrency] "; local sender = "[givecurrency] ";
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local worldMaster = GetWorldMaster();
if name then if name then
if lastName then if lastName then
@ -23,20 +109,30 @@ function onTrigger(player, argc, currency, qty, name, lastName)
end; end;
if player then if player then
currency = tonumber(currency) or nil; if not currencyItems[string.upper(item)] then
player:SendMessage(messageID, sender, "Invalid parameter for item.");
return;
else
item = currencyItems[string.upper(item)];
end
qty = tonumber(qty) or 1; qty = tonumber(qty) or 1;
location = INVENTORY_CURRENCY; location = INVENTORY_CURRENCY;
local added = player:GetInventory(location):AddItem(currency, qty, 1); local invCheck = player:getInventory(location):AddItem(item, qty, 1);
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local message = "unable to add currency";
if currency and added then if (invCheck == INV_ERROR_FULL) then
message = string.format("added currency %u to %s", currency, player:GetName()); -- Your inventory is full.
player:SendGameMessage(player, worldMaster, 60022, messageID);
elseif (invCheck == INV_ERROR_ALREADY_HAS_UNIQUE) then
-- You cannot have more than one <itemId> <quality> in your possession at any given time.
player:SendGameMessage(player, worldMaster, 40279, messageID, item, 1);
elseif (invCheck == INV_ERROR_SYSTEM_ERROR) then
player:SendMessage(MESSAGE_TYPE_SYSTEM, "", "[DEBUG] Server Error on adding item.");
elseif (invCheck == INV_ERROR_SUCCESS) then
message = string.format("Added item %s to location %s to %s", item, location, player:GetName());
player:SendMessage(MESSAGE_TYPE_SYSTEM, "", message);
player:SendGameMessage(player, worldMaster, 25246, messageID, item, qty);
end
end end
player:SendMessage(messageID, sender, message);
print(message);
else
print(sender.."unable to add currency, ensure player name is valid.");
end;
end; end;

View file

@ -15,7 +15,7 @@ Adds <item> <qty> to <location> for player or <targetname>.
function onTrigger(player, argc, item, qty, location, name, lastName) function onTrigger(player, argc, item, qty, location, name, lastName)
local sender = "[giveitem] "; local sender = "[giveitem] ";
local messageID = MESSAGE_TYPE_SYSTEM_ERROR; local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local message = string.format("Unable to add item %u", item); local worldMaster = GetWorldMaster();
if name then if name then
if lastName then if lastName then
@ -27,10 +27,16 @@ function onTrigger(player, argc, item, qty, location, name, lastName)
if player then if player then
item = tonumber(item) or nil; item = tonumber(item) or nil;
if not item then
player:SendMessage(messageID, sender, "Invalid parameter for item.");
return;
end
qty = tonumber(qty) or 1; qty = tonumber(qty) or 1;
if location then if location then
location = tonumber(location) or _G[string.upper(location)]; location = _G[string.upper(location)];
if not location then if not location then
player:SendMessage(messageID, sender, "Unknown item location."); player:SendMessage(messageID, sender, "Unknown item location.");
@ -40,16 +46,22 @@ function onTrigger(player, argc, item, qty, location, name, lastName)
location = INVENTORY_NORMAL; location = INVENTORY_NORMAL;
end; end;
local added = player:getInventory(location):addItem(item, qty, 1);
if added then local invCheck = player:getInventory(location):AddItem(item, qty, 1);
message = string.format("Added item %u of kind %u to %s", item, location, player:GetName());
end; if (invCheck == INV_ERROR_FULL) then
else -- Your inventory is full.
print(sender.."[giveitem] Unable to add item, ensure player name is valid."); player:SendGameMessage(player, worldMaster, 60022, messageID);
return; elseif (invCheck == INV_ERROR_ALREADY_HAS_UNIQUE) then
end; -- You cannot have more than one <itemId> <quality> in your possession at any given time.
player:SendGameMessage(player, worldMaster, 40279, messageID, item, 1);
elseif (invCheck == INV_ERROR_SYSTEM_ERROR) then
player:SendMessage(MESSAGE_TYPE_SYSTEM, "", "[DEBUG] Server Error on adding item.");
elseif (invCheck == INV_ERROR_SUCCESS) then
message = string.format("Added item %s to location %s to %s", item, location, player:GetName());
player:SendMessage(MESSAGE_TYPE_SYSTEM, "", message);
player:SendGameMessage(player, worldMaster, 25246, messageID, item, qty);
end
end
player:SendMessage(messageID, sender, message);
print(message);
end; end;

View file

@ -13,7 +13,18 @@ Positions your character forward a set <distance>, defaults to 5 yalms.
} }
function onTrigger(player, argc, distance, vertical) vertical = {
["UP"] = 1,
["U"] = 1,
["+"] = 1,
["ASCEND"] = 1,
["DOWN"] = -1,
["D"] = -1,
["-"] = -1,
["DESCEND"] = -1,
}
function onTrigger(player, argc, arg1, arg2)
local pos = player:GetPos(); local pos = player:GetPos();
local x = pos[0]; local x = pos[0];
local y = pos[1]; local y = pos[1];
@ -21,37 +32,69 @@ function onTrigger(player, argc, distance, vertical)
local rot = pos[3]; local rot = pos[3];
local zone = pos[4]; local zone = pos[4];
local angle = rot + (math.pi/2); local angle = rot + (math.pi/2);
local worldManager = GetWorldManager();
local messageID = MESSAGE_TYPE_SYSTEM_ERROR; local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "[nudge] "; local sender = "[nudge] ";
local distance = 5;
local direction = 0;
if distance == nil then local checkArg1 = tonumber(arg1);
distance = 5 local checkArg2 = tonumber(arg2);
end;
local px = x - distance * math.cos(angle);
local pz = z + distance * math.sin(angle);
local message = string.format("Positioning forward %u yalms.", distance);
local worldManager = GetWorldManager();
if argc == 1 then if argc == 1 then
worldManager:DoPlayerMoveInZone(player, px, y, pz, rot, 0x0); if checkArg1 then
player:SendMessage(messageID, sender, message); distance = checkArg1;
elseif argc == 2 then
if vertical == "up" or vertical == "u" or vertical == "+" then
y = y + distance;
message = string.format("Positioning up %u yalms.", distance);
worldManager:DoPlayerMoveInZone(player, x, y, z, rot, 0x0);
player:SendMessage(messageID, sender, message);
elseif vertical == "down" or vertical == "d" or vertical == "-" then
y = y - distance;
message = string.format("Positioning down %u yalms.", distance);
worldManager:DoPlayerMoveInZone(player, x, y, z, rot, 0x0);
player:SendMessage(messageID, sender, message);
else else
player:SendMessage(messageID, sender, "Unknown parameters! Usage: \n"..properties.description); player:SendMessage(messageID, sender, "Unknown parameters! Usage: \n"..properties.description);
end; return;
end
elseif argc == 2 then
if checkArg1 and checkArg2 then -- If both are numbers, just ignore second argument
distance = checkArg1;
elseif checkArg1 and not checkArg2 then -- If first is number and second is string
distance = checkArg1;
if vertical[string.upper(arg2)] then -- Check vertical direction on string, otherwise throw param error
direction = vertical[string.upper(arg2)];
else else
player:SendMessage(messageID, sender, "Unknown parameters! Usage: \n"..properties.description);
return;
end
elseif (not checkArg1) and checkArg2 then -- If first is string and second is number
distance = checkArg2;
if vertical[string.upper(arg1)] then -- Check vertical direction on string, otherwise throw param error
direction = vertical[string.upper(arg1)];
else
player:SendMessage(messageID, sender, "Unknown parameters! Usage: \n"..properties.description);
return;
end
else
player:SendMessage(messageID, sender, "Unknown parameters! Usage: \n"..properties.description);
return;
end
end
local message = string.format("Positioning forward %s yalms.", distance);
if direction == 1 then
y = y + distance;
message = string.format("Positioning up %s yalms.", distance);
worldManager:DoPlayerMoveInZone(player, x, y, z, rot, 0x0);
elseif direction == -1 then
y = y - distance;
message = string.format("Positioning down %s yalms.", distance);
worldManager:DoPlayerMoveInZone(player, x, y, z, rot, 0x0);
else
local px = x - distance * math.cos(angle);
local pz = z + distance * math.sin(angle);
if distance < 1 then
message = string.format("Positioning back %s yalms.", distance);
end
worldManager:DoPlayerMoveInZone(player, px, y, pz, rot, 0x0); worldManager:DoPlayerMoveInZone(player, px, y, pz, rot, 0x0);
player:SendMessage(messageID, sender, message);
end; end;
player:SendMessage(messageID, sender, message);
end; end;

View file

@ -0,0 +1,124 @@
require("global");
properties = {
permissions = 0,
parameters = "ssss",
description =
[[
Add/Remove Quests, modify <phase> and <flag 0-32>.
!quest add/remove <quest> |
!quest phase <quest> <phase> |
!quest flag <quest> <flag> true/false |
]],
}
function onTrigger(player, argc, command, var1, var2, var3)
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "[quest] ";
local message = "Error";
if player then
if argc == 2 then
if command == "add" or command == "give" or command == "+" then
if tonumber(var1) then
if player:HasQuest(tonumber(var1)) == false then
player:AddQuest(tonumber(var1));
message = ("adding quest "..var1);
else
message = ("already have quest "..var1);
end
else
if player:HasQuest(var1) == false then
player:AddQuest(var1);
message = ("adding quest "..var1);
else
message = ("already have quest "..var1);
end
end
elseif command == "remove" or command == "delete" or command == "-" then
if tonumber(var1) and player:HasQuest(tonumber(var1)) == true then
player:RemoveQuestByQuestId(tonumber(var1));
message = ("removing quest "..var1);
else
if player:HasQuest(var1) == true then
q2 = GetStaticActor(var1);
if q2 ~= nil then
q3 = q2.actorId;
message = ("removing quest "..var1);
printf(q3);
q4 = bit32.band(q3, 0xA0F00000);
printf(q4);
--player:RemoveQuest(quest.actorName);
end
else
message = ("remove error: either incorrect ID or quest "..var1.." isn't active on character");
end
end
else
message = ("error: command "..command.." not recognized");
end
elseif argc == 3 then
if command == "phase" or command == "step" then
if (tonumber(var1) and tonumber(var2)) ~= nil then
if player:HasQuest(tonumber(var1)) == true then
player:GetQuest(tonumber(var1)):NextPhase(tonumber(var2));
message = ("changing phase of quest "..var1.." to "..var2);
else
message = ("phase error: either incorrect ID or quest "..var1.." isn't active on character");
end
else
message = ("error: invalid parameters used");
end
else
message = ("error: command "..command.." not recognized");
end;
elseif argc == 4 then
if command == "flag" then
if tonumber(var1) and (tonumber(var2) >= 0 and tonumber(var2) <= 32) then
questvar = tonumber(var1);
flagvar = (tonumber(var2));
boolvar = 0;
if var3 == "true" or var3 == "1" or var3 == "on" then
boolvar = true;
elseif var3 == "false" or var3 == "0" or var3 == "off" then
boolvar = false;
elseif var3 == "flip" or var3 == "toggle" then
if player:HasQuest(questvar) == true then
boolvar = not player:GetQuest(questvar):GetQuestFlag(flagvar);
end
else
message = ("error: flag: boolean not recognized");
print(sender..message);
return;
end
var4 = player:GetQuest(questvar):GetQuestFlag(flagvar);
if var4 ~= boolvar then
player:GetQuest(questvar):SetQuestFlag(flagvar, boolvar);
player:GetQuest(questvar):SaveData();
if boolvar == true then
message = ("changing flag "..tonumber(var2).." to true on quest "..questvar);
else
message = ("changing flag "..tonumber(var2).." to false on quest "..questvar);
end
else
message = ("error: flag "..flagvar.." is already set to that state on quest "..questvar);
end
else
message = ("error: command "..command.." not recognized");
end
end
end
end
player:SendMessage(messageID, sender, message);
print(sender..message);
end

View file

@ -13,24 +13,20 @@ Set movement speed for player. Enter no value to reset to default.
} }
function onTrigger(player, argc, stop, walk, run) function onTrigger(player, argc, stop, walk, run)
local s = tonumber(stop) or 0;
local w = tonumber(walk) or 2;
local r = tonumber(run) or 5;
if argc == 1 then if argc == 1 and tonumber(stop) then
s = 0;
w = (tonumber(stop) / 2); w = (tonumber(stop) / 2);
r = tonumber(stop); player:ChangeSpeed(0, w, s, s);
player:ChangeSpeed(s, w, r); player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "", string.format("[speed] Speed set to 0/%s/%s", w,s));
player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "[speed]", string.format("Speed set to 0/%u/%u", w,r));
elseif argc == 3 then elseif argc == 3 then
stop = tonumber(stop) or 0; player:ChangeSpeed(s, w, r, r);
walk = tonumber(walk) or 2; player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "", string.format("[speed] Speed set to %s/%s/%s", s,w,r));
run = tonumber(run) or 5;
if argc == 3 then
player:ChangeSpeed(stop, walk, run, run);
elseif argc == 1 then
player:ChangeSpeed(0, stop/2, stop, stop);
else else
player:ChangeSpeed(0,2,5,5); player:ChangeSpeed(0, 2, 5, 5);
end player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "", "[speed] Speed values set to default");
end end
end end

View file

@ -0,0 +1,39 @@
require("global");
properties = {
permissions = 0,
parameters = "s",
description = "Teleports to Actor uniqueId's position",
}
function onTrigger(player, argc, uID)
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "[warpid] ";
local message = "unable to find actor";
local worldManager = GetWorldManager();
if not player then
printf("[Command] [warpid] Player not found!");
return;
end;
actor = GetWorldManager():GetActorInWorldByUniqueId(uID);
if (actor ~= nil) then
local actorPos = actor:GetPos();
local playerPos = player:GetPos();
if actorPos[4] == playerPos[4] then
worldManager:DoPlayerMoveInZone(player, actorPos[0], actorPos[1], actorPos[2], actorPos[3], 0x00);
else
worldManager:DoZoneChange(player, actorPos[4], nil, 0, 0x02, actorPos[0], actorPos[1], actorPos[2], actorPos[3]);
end
message = string.format("Moving to %s 's coordinates @ zone %s, %.3f %.3f %.3f ", uID, actorPos[4], actorPos[0], actorPos[1], actorPos[2]);
end ;
player:SendMessage(messageID, sender, message);
end

View file

@ -0,0 +1,63 @@
require("global");
properties = {
permissions = 0,
parameters = "ssss",
description =
[[
Warps to name of player, or warps first player to second player
<target name> |
<1st target name> <2nd target name>
]],
}
function onTrigger(player, argc, name, lastName, name2, lastName2)
local messageID = MESSAGE_TYPE_SYSTEM_ERROR;
local sender = "[warpplayer] ";
if name and lastName then
p1 = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil;
end;
if name2 and lastName2 then
p2 = GetWorldManager():GetPCInWorld(name2.." "..lastName2) or nil;
end;
if not player then
printf("[Command] [warpplayer] Error! No target or player specified!");
return;
end;
local worldManager = GetWorldManager();
if argc == 2 then
if not p1 then
printf("[Command] [warpplayer] Error! Invalid player specified!");
player:SendMessage(messageID, sender, "Error! Invalid player specified!");
return;
else
local pos = p1:GetPos();
worldManager:DoZoneChange(player, pos[4], nil, 0, 0x02, pos[0], pos[1], pos[2], pos[3]);
player:SendMessage(messageID, sender, string.format("Moving to %s %s 's coordinates.", name, lastName));
end;
elseif argc == 4 then;
if not p1 or not p2 then
printf("[Command] [warpplayer] Error! Invalid player specified!");
player:SendMessage(messageID, sender, "Error! Invalid player specified!");
return;
else
local pos = p1:GetPos();
local pos2 = p2:GetPos();
worldManager:DoZoneChange(p1, pos2[4], nil, 0, 0x02, pos2[0], pos2[1], pos2[2], pos2[3]);
player:SendMessage(messageID, sender, string.format("Moving %s %s to %s %s 's coordinates.", name, lastName, name2, lastName2));
p1:SendMessage(messageID, sender, string.format("You are being moved to %s %s 's coordinates.", name2, lastName2));
end;
else
if player then
player:SendMessage(messageID, sender, "Unknown parameters! Usage: "..properties.description);
end;
return;
end;
end;

View file

@ -51,6 +51,12 @@ INVENTORY_KEYITEMS = 0x0064; --Max 0x500
INVENTORY_EQUIPMENT = 0x00FE; --Max 0x23 INVENTORY_EQUIPMENT = 0x00FE; --Max 0x23
INVENTORY_EQUIPMENT_OTHERPLAYER = 0x00F9; --Max 0x23 INVENTORY_EQUIPMENT_OTHERPLAYER = 0x00F9; --Max 0x23
-- INVENTORY ERRORS
INV_ERROR_SUCCESS = 0;
INV_ERROR_FULL = 1;
INV_ERROR_ALREADY_HAS_UNIQUE = 2;
INV_ERROR_SYSTEM_ERROR = 3;
-- CHOCOBO APPEARANCE -- CHOCOBO APPEARANCE
CHOCOBO_NORMAL = 0; CHOCOBO_NORMAL = 0;

55
data/scripts/shop.lua Normal file
View file

@ -0,0 +1,55 @@
--[[
Shop Buy/Sell Functions
--]]
function purchaseItem(player, location, itemId, quantity, quality, price, currency)
local worldMaster = GetWorldMaster();
local invCheck = -1;
if (player:GetInventory(INVENTORY_CURRENCY):HasItem(currency, price)) then
invCheck = player:GetInventory(location):AddItem(itemId, quantity, quality);
if (invCheck == INV_ERROR_FULL) then
-- Your inventory is full.
player:SendGameMessage(player, worldMaster, 60022, MESSAGE_TYPE_SYSTEM);
elseif (invCheck == INV_ERROR_ALREADY_HAS_UNIQUE) then
-- You cannot have more than one <itemId> <quality> in your possession at any given time.
player:SendGameMessage(player, worldMaster, 40279, MESSAGE_TYPE_SYSTEM, itemId, quality);
elseif (invCheck == INV_ERROR_SYSTEM_ERROR) then
player:SendMessage(0x20, "", "[DEBUG] Server Error on adding item.");
elseif (invCheck == INV_ERROR_SUCCESS) then
player:GetInventory(INVENTORY_CURRENCY):removeItem(currency, price);
if (currency == 1000001) then -- If Gil
-- You purchase <quantity> <itemId> <quality> for <price> gil.
player:SendGameMessage(player, worldMaster, 25061, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, price);
elseif (currency == 1000201 or currency == 1000202 or currency == 1000203) then -- If Grand Company seal
-- You exchange <quantity> <GC seals> for <quantity> <itemId> <quality>.
player:SendGameMessage(player, worldMaster, 25275, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, price, player.gcCurrent);
elseif (currency >= 1000101 and currency <= 1000123) then -- If Guild mark
-- You trade <quantity> <itemId> <quality> for <quantity> <itemId> <quality>.
player:SendGameMessage(player, GetWorldMaster(), 25071, MESSAGE_TYPE_SYSTEM, currency, 1, itemId, 1, price, quantity);
end
end
else
-- You do not have enough gil. (Should never see this)
player:SendGameMessage(player, worldMaster, 25065, MESSAGE_TYPE_SYSTEM);
end
return
end
function sellItem(player, itemId, quantity, quality, itemPrice, slot, currency)
local worldMaster = GetWorldMaster();
local cost = quantity * itemPrice;
player:GetInventory(INVENTORY_CURRENCY):AddItem(currency, cost);
player:GetInventory(INVENTORY_NORMAL):RemoveItemAtSlot(slot, quantity);
-- You sell <quantity> <itemId> <quality> for <cost> gil.
player:SendGameMessage(player, worldMaster, 25075, MESSAGE_TYPE_SYSTEM, itemId, quality, quantity, cost);
end