1065 Commits

Author SHA1 Message Date
Filip Maj
63f0b024ac Finished the Souls Gone Wild quest.... mostly 2022-06-16 01:53:12 -04:00
Filip Maj
67db1035ed Added missing CNJ and Gridania npcs 2022-04-26 18:15:50 -04:00
Filip Maj
c865975df7 Adding snpc table schema. Updating server zones/privatearea tables 2022-04-15 16:10:42 -04:00
Filip Maj
aef0f2b400 Renamed QFLAG constants and moved them to quest.lua 2022-04-15 12:35:06 -04:00
Filip Maj
16c62a08d8 Added missing npcs 2022-04-15 12:34:07 -04:00
Filip Maj
6cb107870f Merged dbs 2022-04-13 21:43:43 -04:00
Filip Maj
9a2f8ef89a Merge branch 'Jorge/quest_system' into ioncannon/quest_system 2022-04-13 20:12:38 -04:00
Filip Maj
524f415b44 Fixed bug when two chars have slot == 2 2022-04-13 20:04:57 -04:00
Filip Maj
5c0d2c1d7f Fixed up some lua scripts. Fleshed out the dream stuff for Hildie quests. NOTE: Finish player.lua as it has pseudo code. 2022-04-13 20:03:46 -04:00
CuriousJorge
a7b1b79461 Hildibrand series of quests all in. Requires inn dream handling and some retail accuracy double-checking to finish it off. Misc script fixes also.
===============================
Nudgenpc.lua    - Added a command variation
Testmapobj.lua - Added !help documentation
DftWil.lua            - Corrected an npc name/function
Player.cs             - Changed Dalamud packet to default to 7, not 0.  Fixes the moon not displaying in a specific Hildibrand cutscene
Etc5g0.lua          - Made quest accepting retail-accurate with how it displayed messages/ended the TalkEvent
Etc5g1.lua          - Added Bed !.  Kinda kludged in atm since it's a pre-accepted quest state.
Etc5u1.lua          - Same as above
Etc5l1.lua           - Quest "Private Eyes" scripted.
Etc5l2.lua           - Quest "Mysteries of the Red Moon" scripted
Etc5l3.lua           - Quest "Prophecy Inspection" scripted
2022-04-13 11:45:49 -04:00
Filip Maj
c3b4735cc5 Added missing dialog to some npcs in Legends Adrift. Finished Never Shall the Twain Meet. 2022-04-12 01:07:17 -04:00
Filip Maj
ac22637b4f Got Fade to White 99% scripted out. Got Path Companion data all setup and saving/loading. Fixed the BgKeepouts and they properly show their msgs. Added quests to MarketEntrances. Fixed MarketEntrances. Hooked cutscene book to the Patch Companion you use. 2022-04-12 01:06:12 -04:00
CuriousJorge
01d05b5cee Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-04-03 01:14:13 -04:00
CuriousJorge
d50bfef2e5 Minor script revision + new quest
warp.lua - Switched to warp type 0x16 for flipping between city zones.  Zero gameplay interruption with this type.
etc5u1 - Added in a spawn location for privateArea
etc5g1 - Scripted, aside from the means of accepting the quest which requires special handling to trigger the intro CS for it.
2022-04-03 00:57:24 -04:00
Filip Maj
a5a039ce3d Added the other two Shposhae quests; A Slippery Stone and Cutthroat Prices. Also modified the PopFlyingShip script to move the quest along. 2022-04-02 13:34:32 -04:00
Filip Maj
514610f006 Minor fix to Call of Booty. 2022-04-02 12:47:19 -04:00
Filip Maj
159242068d Added Call of Booty ( ͡° ͜ʖ ͡°) 2022-04-02 12:45:53 -04:00
Filip Maj
a6ee42094c Finished 'What a Pirate Wants' (lol what a Pirate Needs, what a Pirate, whatever keeps rum in my arms and I'm thanking you for giving it to me.) 2022-04-02 12:26:18 -04:00
Filip Maj
6bbe272d48 Added a buttload of side quests. This should mean all talky quests and 'kill x things' quests are done. Also updated the attention messages as they were using the wrong one for getting items or killing mobs. Fixed some journal issues on various quests as well. 2022-04-02 11:52:32 -04:00
Filip Maj
938cca0298 Added An Inconvenient Dodo and Besmitten and Besmirched. 2022-03-30 00:59:56 -04:00
Filip Maj
e53e54b4bf Fixed more quests 2022-03-30 00:17:59 -04:00
Filip Maj
f6ff56299f Fixed up some more quests! 2022-03-29 23:56:08 -04:00
Filip Maj
a1bb84e80d Fixed up Food for Thought (emotes work now) and Have You Seen my Son (bnpc works). 2022-03-29 22:57:02 -04:00
Filip Maj
4d2c80a8ee testbnpckill was missing it's extension 2022-03-29 22:01:03 -04:00
Filip Maj
c2169576c2 Fixed Til Death Do Us Part and Beryl Overboard so that the proper attention msgs appear. Also added missing params to the funcs defining the objective quantity. 2022-03-29 22:00:18 -04:00
Filip Maj
4d424e57f9 Adding the rest of the wld quests: Sanguine Studies, Secrets Unearthed, and Rustproof. 2022-03-29 21:19:35 -04:00
CuriousJorge
4494b30285 Quest fixes
Etc5u1 & Etc5g1 - Added handling for the Ul'dah Inn NPC to re-issue an item as needed, otherwise play his other dialog.
Music - Made it play current zone's music if no id present.
2022-03-16 18:52:02 -04:00
CuriousJorge
74713f3dd6 Misc GM command fixes + ChangeJobCommand.lua
Anim - Cleaned up some.  It had old code sitting in it for whatever reason despite not affecting anything.
Setstate, Warpplayer & Yolo - Fixed them up so they function again
ChangeJobCommand - Just the script filled out to handle the equipping/dequipping of job stones, but it can cause issues, particularly with how the server handles a 'job' vs. a class, along with checking against skill compatibility.
2022-03-13 20:35:29 -04:00
CuriousJorge
b08827568c Chocobo stuff:
PopulaceChocoboLender - Made rental time 10 minutes again (as retail had it).  Added Vesper Bay NPC's rental location as close as I could get it from a blurry source.
ChocoboRideCommand - Fixed the method used to pull a zone's music so the script doesn't fail.
2022-03-13 18:26:20 -04:00
CuriousJorge
b34f214e67 Quests + Minor fixes
MarketEntrance - Adjusted events parameter so it works again
Warp - Added shortcut for switching between a given town's zones so I can stop having to look up the right zone id
Weather - Added shortcut for weather ids to +8000 to the value if the're within a certain range.
DftSea - Inn NPC check
etc5u0 - Used a constant in place of a value, updated a constant's name.
etc5l0 -  Fully scripted.
etc5u1 - Mostly scripted.  Requires Dream handling and privArea + NPC placement.
etc5g1 - Mostly scripted.  Requires Dream handling and privArea + NPC placement.
2022-03-13 17:45:10 -04:00
CuriousJorge
e94c037fb5 Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system
# Conflicts:
#	Data/scripts/commands/EmoteSitCommand.lua  - Resolved using Theirs
2022-03-11 19:21:42 -05:00
Filip Maj
65ee91e49c Finished Treasures of the Main and Legends Adrift. Fixed quests appearing in private areas (echos). Fixed other bugs. Implemented NPC Linkshells. Added more options to nudge command. Added nudgenpc command. Added testbnpckill command. 2022-03-11 02:17:46 -05:00
CuriousJorge
01ec313ffb DftFst.lua - about as documented as I can get it for now. Will finalize some NPC argument checks next time.
quest.lua - Script refactored.  Moved as much as possible out of the main function to tidy it up.  Folded in a complete-quest function from another script.  Only works with quest id numbers for now.  String support (eg. Man0u0) to come in another commit.
ObjectInnDoor.lua - Fixed it to handle events again with the current system.
2022-03-09 22:23:10 -05:00
Filip Maj
ebba56602c Removed automatic Left Instance msg, as it only happens when running out of a PrivateArea_Exit. More M0l1 work. 2022-03-05 01:28:28 -05:00
Filip Maj
49c6fdbd51 Added functionality to handle NPC LSes in quests. Linked the rest of the sequences up for Man0l1. 2022-03-05 01:02:41 -05:00
CuriousJorge
08557f41fb Minor fixes
- InstanceRaid Guide : Added DefaultTalk handling for the npcs we have currently.  Included a couple commented-out client functions for two of the raids.
- EmoteSitCommand : Added eventType to the function so sitting on environment objects works again.
- Man0u0 : SourceTree added hunk-change garbage during a conflict resolving during the last merge. I just replaced it with the raw of that commit so it matches what it should have been.
- DftFst : Added the Gridania InstanceRaidGuide NPCs to the list for documentation sake, even though it'd never be called from that script with how things are currently set up.
2022-03-04 23:12:28 -05:00
Filip Maj
a618e69dbd Fixed args on commands due to triggername becoming eventType and eventName 2022-03-04 22:55:30 -05:00
CuriousJorge
02fe9e070d Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system
# Conflicts:
#	Data/scripts/commands/EmoteStandardCommand.lua
#	Data/scripts/quests/man/man0g0.lua
#	Data/scripts/quests/man/man0g1.lua
#	Data/scripts/quests/man/man0u0.lua

Resolved using Theirs.
2022-03-04 21:04:17 -05:00
Filip Maj
bf20993e58 Finished sequences 55, 60, 65 for Treasures of the Main. 2022-03-04 20:33:02 -05:00
Filip Maj
2817560217 Got the emote sequence for Treasures of the Main working. Got the duty started but there are issues on zoning. 2022-03-04 02:20:56 -05:00
Filip Maj
765cf194c5 Removed more dead scripts. Exported missing sql files. 2022-03-03 23:33:55 -05:00
Filip Maj
b57f91470a Deleting more useless scripts. Moved all the elevator scripts into 1 base script. 2022-03-03 20:03:36 -05:00
Filip Maj
2cb6a9f6bd Added back loading defaulttalk npcs through script. Should speed up warps now! Added loading mapobj ifno through a db table, removing the need for unique scripts. Deleted ported mapobj scripts. 2022-03-03 19:34:33 -05:00
Filip Maj
b773098abf Added the PGL200 quest The House Always Wins. Fixed quest instances not being set on spawn. Fixed PrivateAreaPast. Added You have left the instance messages when leaving a PrivateArea. Fixed EmoteEvents. DefaultTalk has been disabled temporarily to speed up warps. 2022-03-03 01:59:13 -05:00
Filip Maj
f491c63b98 The journal update msg shows even when completing quests now. Added Revenge on the Reavers, Till Death Do Us Part, Beryl Overboard, Have You Seen My Son, and Food for Thought. 2022-03-01 14:29:59 -05:00
CuriousJorge
023527efa3 Further work on DefaultTalks
- DftFst - Every uniqueId script covered from the previous system.  Still a lot of functions to still map and actors to pose & position for them.
- AfterQuestWarpDirector - Added Man0g1 as a check.
- Nuked PopulaceStandard uId scripts for Forest region since unneeded now.
2022-02-26 23:15:20 -05:00
Filip Maj
96f9119cca Fixed Waste Not Want Not now that the quest system is final. 2022-02-24 22:59:06 -05:00
Filip Maj
f84899ff2e Added Assessin the Damage 2022-02-24 22:48:55 -05:00
CuriousJorge
a87244d13b - man0g0 - Majority of the work ported from the old quest system. Still polish to be had and fringe cases to deal with (especially relogging)
- man0g1 - Initial privateArea mostly scripted.
- SimpleContent30010 - Fixed Yda/Papalymo Id being backwards, added Active states to match retail
- QuestDirectorMan0g001-  Updated to play itself out (this is a mess to wrap my head around).  Mostly sorta kinda working on both DoW & DoM tutorials.  End cutscene on DoW not firing currently, will fix later.
2022-02-24 22:24:08 -05:00
Filip Maj
c5198783a1 Adding Sleepless in Eorzea, Bridging the Gap, and The Search for Sicksa. 2022-02-24 20:31:05 -05:00
Filip Maj
b9ab842fdd Added Spores on the Brain 2022-02-24 19:31:32 -05:00
Filip Maj
e8ee907477 Added A Bitter Oil to Swallow 2022-02-24 19:23:11 -05:00
Filip Maj
b4227cdc44 Added Sour Grapes 2022-02-24 19:07:09 -05:00
Filip Maj
59f4e4bbd5 Fixed bug in Hearing Confessions. Added Letting Out Orions Belt and Sniff Out a Profit. The former still needs the correct attention message though when talking to a NPC. 2022-02-24 18:46:55 -05:00
Filip Maj
c9f18f5415 Added Of Archons and Muses 2022-02-24 12:40:59 -05:00
Filip Maj
495bdf4ba6 Added Hearing Confessions. 2022-02-24 02:16:28 -05:00
Filip Maj
b46160763c Finished In the Name of Science 2022-02-24 01:34:26 -05:00
Filip Maj
3393eb4c9d Trading Tongueflaps is done! 2022-02-24 00:54:03 -05:00
Filip Maj
7de153dde1 Fixed markers in etc3u0 2022-02-24 00:03:16 -05:00
Filip Maj
0faa056589 Added A Call to Arms. Fixed up Seeking the Seers. 2022-02-24 00:00:58 -05:00
Filip Maj
90115f7c83 Added Tug of the Whorl. Fixed up prereqs not working when using debug command. Fixed giveexp command. Added seq constants. 2022-02-23 23:10:11 -05:00
CuriousJorge
682ddd9cae - Fixed !anim targeting the incorrect actor.
- Etc5u0 scripted start to finish.  Ul'dah Inn quest.
- DftWil - Added quest checks to the Inn NPCs.
- DfFst - Commiting what's been done thus far.  fst0Town01 zone nearly done.  Still have 100 something fst0Town01a & field npcs to add.
- Removed some fst0Town01 uniqueId scripts
2022-02-23 20:52:25 -05:00
CuriousJorge
8c70d0ddb6 - man0u0 : Updated script to work with the recent changes in how quest data is requested. 2022-02-20 23:32:47 -05:00
Filip Maj
5c49563790 Removed useless uniques after DftSea and DftWil got replaced 2022-02-20 23:23:28 -05:00
Filip Maj
c6a372ad83 Fixed replaced quests not being added to the complete list 2022-02-20 23:20:45 -05:00
CuriousJorge
d2e814b4ee Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-02-20 23:05:49 -05:00
Filip Maj
0cdeb5d9ac Got tutorial quests working again. Integrated Jorges DftSea work, thanks! 2022-02-20 23:03:16 -05:00
CuriousJorge
fac8f269e7 Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system
# Conflicts:
#	Data/scripts/player.lua  - Resolved.  Using theirs.
2022-02-20 22:57:01 -05:00
CuriousJorge
d06152be07 Commiting more work before merging in another branch.
- DftFst - More actors added
- Trl0g1/Trl0l1 - Removed a stray ] causing the script to not function.
2022-02-20 22:54:31 -05:00
Filip Maj
0b67f8e436 Fixed bugs and edited scripts causing the limsa intro to fail. 2022-02-20 22:40:35 -05:00
CuriousJorge
7fea45e1f8 Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-02-20 21:33:50 -05:00
CuriousJorge
696d355ae9 Commit work on DftFst before merging in some fixes unrelated issues. 2022-02-20 21:32:43 -05:00
Filip Maj
bbbab356af Fixed a bunch of bugs Jorge found. Readded tutorial quests back. 2022-02-20 21:30:09 -05:00
CuriousJorge
594e08f990 Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-02-20 15:10:49 -05:00
CuriousJorge
89287844f7 Player.lua - Added fallback for second half of the man0u0 tutorial to get an onNotice kicked, so it can eventually handle it and resume gameplay from a disconnect. 2022-02-20 15:06:17 -05:00
Filip Maj
c240096eb8 Added gamedata quest table. 2022-02-20 12:42:29 -05:00
Filip Maj
08e7a9cfd4 Added sql schema change to completed quests 2022-02-20 12:41:21 -05:00
Filip Maj
25f1b0fd95 Added debug script for setting quest completion 2022-02-20 12:39:34 -05:00
Filip Maj
c677479a03 Added completed quest sendback. 2022-02-20 12:06:48 -05:00
Filip Maj
306f4ef346 Got aetheryte map and completed quest work values... working. 2022-02-19 01:17:50 -05:00
Filip Maj
a2c4d077e9 Fixed quest loading 2022-02-17 21:30:06 -05:00
CuriousJorge
7e5ca6e013 Added Foundation Day 2012 actors to DftWil for now just so they can talk.
Added a Chocobo to it also that we already had spawned, unsure if authentic or not, added a comment reflecting that.
Cleaned up more orphaned scripts from Wil region.
2022-02-17 20:03:15 -05:00
Filip Maj
02cb0a3f43 Refactored quest state system seems to work! 2022-02-17 13:22:18 -05:00
CuriousJorge
dc1458c52d - Player.lua - Fixed typo on ClearData() for Ul'dah intro
- DftSea - 96% finished
- DftWil - minor comment addition
- EmoteStandardCommand - Added the new event params so the script functions again
- Mass deletion of all PplStd & PplShopSalesman for La Noscea NPCs.  No longer needed
2022-02-17 02:49:59 -05:00
Filip Maj
1523ae200b Finished quest state system idea 2022-02-16 15:32:54 -05:00
Filip Maj
aae051d73f Capitalized the DataObject class. 2022-02-16 15:30:32 -05:00
Filip Maj
9097e557ed Removed the state and custom name columns from the enpc table. Renamed server_spawn_locations to server_eventnpc_spawn_locations. Renamed animationId to motionPack. 2022-02-13 19:24:09 -05:00
Filip Maj
cfe6ef2e5e Merge branch 'Jorge/quest_system' into ioncannon/quest_system 2022-02-13 18:57:08 -05:00
Filip Maj
d26aaed953 Added a bunch of npcs to the db 2022-02-13 18:51:23 -05:00
Filip Maj
8d5f4465e3 New test gm scripts to help with positioning populace npcs 2022-02-13 18:50:48 -05:00
Filip Maj
214d730a58 Added warp to public and private areas shortcut. Fixed counter printout bug. Fixed some commands. Fixed handling of the chocobo lender at the ferry docks. 2022-02-13 18:48:22 -05:00
CuriousJorge
b6c9825b2d - Man0u0 about as polished as one can get the Talking sections for now, minus some very specific retail quirks that need replicating at some point (all revolving around the starting 15 seconds of the forced tutorial)
- Man0u1 barely started.  Just enough there to get the player out of the PrivateArea and into the public zone.
- All of the old Populace uniqueId scripts for both quests nuked into high orbit.
- DftSea:  Master list of function names and argument counts added to the list.  Will be whittling away at this over the coming week.
- GM Warp: For whatever reason using "" to compare against a nil wasn't working anymore.  Set it to nil instead.
2022-02-13 13:18:20 -05:00
CuriousJorge
acf953e909 DftFst: Added a param handling to Kinnison on DftFst since it'd crash the client otherwise.
Etc3g0: Polished up the script, made it as authentic to retail as I could get it barring reward hand-out and starting the quest
Etc5g0: Ported the quest over from the old scripting setup.
Man0u1: Still very early wip.
2022-02-10 19:35:04 -05:00
CuriousJorge
4fe8f77887 Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-02-08 21:41:22 -05:00
CuriousJorge
96cb8070be Man0u0 & Man0u1 work progress.
Man0u0 nearly finished.  Needs some misc. background actors Id'd and placed, and some additional bug-testing.
Man0u1 still very early.  Initial area's actors mostly scripted.
2022-02-08 17:35:29 -05:00
Filip Maj
9f077190a3 Renamed some funcs, and fleshed out a ton on man0l1. Various related things were also added. 2022-02-07 05:13:34 -05:00
CuriousJorge
0465bf6b8d Merge remote-tracking branch 'origin/ioncannon/quest_system' into Jorge/quest_system 2022-02-06 23:18:59 -05:00
Filip Maj
0ac53e23ad Fixed warp to allow private areas 2022-02-06 23:17:59 -05:00
CuriousJorge
e6d5d5a530 Merge branch 'ioncannon/quest_system' of https://bitbucket.org/Ioncannon/project-meteor-server into Jorge/quest_system 2022-02-06 20:40:25 -05:00
Filip Maj
335efcc81e Fixed Quest ENPC bug and converted over Man0l1 2022-02-06 20:08:53 -05:00
CuriousJorge
fb9d4026a5 Merge branch 'ioncannon/quest_system' of https://bitbucket.org/Ioncannon/project-meteor-server into Jorge/quest_system 2022-02-06 14:49:31 -05:00
CuriousJorge
68a2685cf1 Man0u0 wip progress. 2022-02-06 12:36:15 -05:00
Filip Maj
8b3431e557 Changed how Quest ENPCs work. They should now automatically update themselves whenever data is update for immediate effect changes. Fixed wrong map qflag value. Fixed quest gm command. Fixed Director actorId clobbering areaMasters. 2022-02-06 12:12:26 -05:00
Filip Maj
b11007b263 Quest schema in db changed 2022-02-05 22:40:24 -05:00
CuriousJorge
2cbb48621b Merge branch 'ioncannon/quest_system' into Jorge/quest_system 2022-02-05 18:26:03 -05:00
Filip Maj
f574f5b103 Revert lua engine UserData policy 2022-02-05 18:19:40 -05:00
Filip Maj
8d647ae6b0 This script was missing for some reason 2022-02-05 18:17:14 -05:00
Filip Maj
f374ee3be9 More changes 2022-02-05 18:14:23 -05:00
Filip Maj
37d04344ae Forgot file 2022-02-05 18:01:16 -05:00
Filip Maj
68e55a1c76 Added changes to how zones/areas are accessed in the lua scripts too. 2022-02-05 18:00:09 -05:00
Filip Maj
4e0cf36552 Refactored some actor field names 2022-02-05 17:48:49 -05:00
CuriousJorge
4e5a07afa4 Merge branch 'ioncannon/quest_system' into Jorge/quest_system 2022-02-05 14:21:57 -05:00
Filip Maj
563118372a Refactored how zones work. Cleaned out a lot of duplciations and smoothed out how Zones/PrivateAreas work. 2022-02-05 14:05:32 -05:00
CuriousJorge
4fc5762d41 Teleport command touch-ups.
PopulaceCompanyWarp made to look more retail authentic.  Can't figure out how to make it not play the 'npc untargeted' sound though like retail.
Music command has second argument for transition type.  Added an overloaded function in Player.cs to support this.
Setappearance adjusted to work again on player targets.
DftWil updated to cover near everything.
Re-added shop-related luas that were removed for some reason.
2022-02-05 13:56:58 -05:00
Filip Maj
56ba641e2a Fixed PrivateAreas not working due to a bad actor id colliding with players. 2022-02-05 12:15:22 -05:00
Filip Maj
3ad30460d8 Removed spawn locations warping. Fixed event packet str len. Fixed some scripts. Fixed doors not working. 2022-02-05 09:55:18 -05:00
Filip Maj
ff074c8394 Bunch of shop scripts added (by Jorge) 2022-01-29 10:01:31 -05:00
CuriousJorge
bad51717c2 Minor script fixes
=============
ChocoboRideCommand - Fixed the mount speed to be retail accurate.
TeleportCommand            - Added anima costs, mount check, and placeholder for Favoured destinations
nudge/spawn/warpid        - Plus 1 to GetPos() arrays
2022-01-28 02:29:45 -05:00
Filip Maj
26fd79bea5 Removed all the unique talk defaults for Wil region (thx Jorge). Got most of man0l0 working with the new system. Fixed nullterm str parsing. 2022-01-27 17:38:15 -05:00
Filip Maj
6e869af4fb Fixed flags being backwards 2022-01-26 01:17:59 -05:00
Filip Maj
93c90df797 Got limsa opening working again 2022-01-26 01:15:02 -05:00
Filip Maj
c38caffaf1 Fixed bug with dialog treating all characters as men. 2022-01-25 22:55:39 -05:00
Filip Maj
958a87edf2 Updated Scripts, removed all the old unique ones for the opening quest. 2022-01-25 22:54:44 -05:00
Filip Maj
2279ee7017 Started mass overhaul of quests and related components like small talk. Fixed some scripts. More fixes required. 2022-01-24 23:49:10 -05:00
Filip Maj
df49eefadb Added recipe resolver 2021-02-26 21:10:01 -05:00
CuriousJorge
6e1f13d17a Merged in CuriousJorge/ffxiv-classic-server/dev_local (pull request #72)
Approved-by: Elise <robotbrainify@gmail.com>
Approved-by: Filip Maj <filipmaj@gmail.com>
2020-10-03 16:41:40 +00:00
CuriousJorge
bbf49123b6 Follow-up to prior commit with script changes I forgot to commit. 2020-09-25 18:23:09 -04:00
CuriousJorge
48d996bd4f SetPushEventConditionWithTriggerBox & EventList.cs - Made changes to PushBoxEventCondition so it can function ingame if provided the correct parameters in the eventConditions in the gamedata_actor_class SQL. These are used for the Market Wards entrances in each city
MarketEntrance.lua       - Script mostly laid out and documented.  Some debugging info left in while various warp locations and PrivateAreas still need finishing up.

CraftCommand.lua  - WIP on crafting menu + minigame.  Menu flow worked out for the most part, it's just a matter of plugging in various data for them to replace the debugging values I set currently.
DummyCommand.lua - WIP on Mining minigame.  Still lots missing but it's a start.  Cannot use mining nodes ingame currently without modifying KickEventPacket.cs

Removed orphaned individual ShopSalesman scripts since their info was tabled into a single script awhile back.
2020-09-25 18:15:54 -04:00
CuriousJorge
8ddcd24704 Merged Ioncannon/project-meteor-server:develop into master 2020-09-25 16:19:02 -04:00
PW Anon
1c5fd48d03 Merged in Resharc/project-meteor-server/issue-25 (pull request #68)
Fix to incorrect skill being given upon changing to a new class for the first time.

* Ported over changes from resharc/ffxiv-classic-server and merged into new branch.

* Changed EquipAbilitiesAtLevel(...) to use the level supplied, instead of GetLevel(), which should fix issue 25.

* Revert "Ported over changes from resharc/ffxiv-classic-server and merged into new branch."

    This reverts commit fce3fb5b899c6150230245d73f25255ae2b93549.

Approved-by: Filip Maj <filipmaj@gmail.com>
2020-04-13 20:49:38 +00:00
Filip Maj
31ec4efdcf Fixed GSM offhand not showing the glow. Fixed SQL file db issue. 2020-03-31 18:18:24 -04:00
Filip Maj
20b1ec18a9 DOH/DOL graphic support.
Adding the rest of the missing item graphics for DOH/DOL weapons. Modified the equip script to also set the correct "special" graphics for the workbenches and such.
2020-03-29 13:33:27 -04:00
Filip Maj
41b891feaf Adding scripts for new npcs. 2020-03-15 01:07:17 -04:00
Filip Maj
47a2eddaf0 Adding NPCs in fields from captures. Updated Shop script.
The captures we have are full of npcs that were never imported; finally did so. Updated shop script with Jorge's work.
2020-03-15 01:05:43 -04:00
Filip Maj
2e5cf8dfec Updating tables for missing chara graphics and npcs.
Added missing neck and index finger graphics to character_appearance. Adding a bunch of monster classes and chocobo classes/spawns for getting the license. Also the CRP npcs.
2020-03-14 13:03:24 -04:00
Filip Maj
eecb5ac8a1 Fixed appearance bugs. Fixed a lua arg bug.
-Due to using ordinals instead of keys, the NPC voices were set wrong. This is fixed now, as all appearance loading from the DB uses keys now.
-Fixed hairVariation not loading for lobby/map server.
-Fixed a lua arg bug.
2020-03-13 23:17:12 -04:00
Filip Maj
99c8aff702 Fixed event status packet using the wrong event type. Changed kickevent in player class to use notice type. 2020-02-28 00:05:46 -05:00
Filip Maj
d588dd0348 Turns out the player also spawns out of the inn for the nightmare. Fixed (and renamed a spawn). 2019-07-27 23:11:39 -04:00
Filip Maj
7883143089 Added script to handle what happens after a dream that causes a warp. Adds a quest for Hildi ones, warps all other 3. 2019-07-27 22:43:47 -04:00
Filip Maj
c753e61b62 Merge remote-tracking branch 'origin/develop' into develop 2019-07-27 21:55:31 -04:00
Filip Maj
42f0046ee7 Reimplemented dream packets. Fixed instance update bug that was locking up client when waking up. When going to sleep the proper position is saved. Still need to handle if the player logs out in the inn vs sleeping. 2019-07-27 21:55:07 -04:00
Filip Maj
aa54fb11cc Reimplemented dream packets. Fixed instance update bug that was locking up client when waking up. When going to sleep the proper position is saved. Still need to handle if the player logs out in the inn vs sleeping. 2019-07-27 21:54:05 -04:00
Filip Maj
e4d43d952b Removing the duplicate bugs after renaming folders to upper case (pls don't break). 2019-07-27 20:13:16 -04:00
Filip Maj
ae3a6f1b27 Leftover file from previous commits. 2019-07-26 23:27:33 -04:00
Filip Maj
5724cf53bf Removed weird lowercase refs. 2019-07-26 23:26:37 -04:00
Filip Maj
0ec9c5576c Packet refactoring. 2019-07-26 23:24:06 -04:00
Filip Maj
96641865bc Added Goobbue to the checks. 2019-07-25 20:35:12 -04:00
Filip Maj
ea7bf4b86d Mount music will now persist while mounted through zoning. Shit forgot gobbue. 2019-07-25 20:28:57 -04:00
Filip Maj
94d1915acb Fixed dismount message on rentals. 2019-07-25 20:00:46 -04:00
Filip Maj
02e41f6103 Bugfix. 2019-07-25 19:51:11 -04:00
Filip Maj
b627ecf0fe Finished filling out lua script for rentals/summons/new chocos. 2019-07-25 19:46:05 -04:00
Filip Maj
ca4f00cfe3 Fixed bug where no name would appear in the post-chocobo naming cutscene. 2019-07-25 19:44:22 -04:00
Filip Maj
8687e43191 Fixed actors not being resent on login into already available session due to those actors being in the instance list but not the client. Added chocobo rental code. 2019-07-11 12:13:23 -04:00
Yogurt
d3027c3b26 ReAdding Azia's fixes that got removed when I fucked up on the license change. 2019-06-24 18:39:11 -04:00
paru
afd056d82d Merged in parulina/project-meteor-server/linux_fixes (pull request #65)
Linux fixes
2019-06-22 18:59:54 +00:00
paru
e6802d514c Fix lowercase Actors/Group/work 2019-06-21 03:17:16 +02:00
parulina
66ed26617d Replace xcopy with built-in VS content copy 2019-06-21 02:48:50 +02:00
parulina
f5bf5956b2 Updated NLog to fix mono console output under Linux and removed NLog.config/schema 2019-06-21 02:48:28 +02:00
Filip Maj
c14b117947 Fixing World nlog. 2019-06-19 01:16:49 -04:00
Filip Maj
91549bff7a Updated Map Server namespace. Moved all other data folders (www and sql) to data folder. Renamed boot name to Project Meteor. 2019-06-19 01:10:15 -04:00
Filip Maj
18ef69f3d1 Updated git ignore as it's causing Debug.cs to be missing. 2019-06-19 00:45:12 -04:00
Filip Maj
104f3daf7c Readme update. 2019-06-19 00:19:51 -04:00
Filip Maj
b85b35a2b6 Renamed assemblies. 2019-06-19 00:17:39 -04:00
Filip Maj
0f61c4c0e1 Cleaned up namespaces (still have to do Map Project) and removed references to FFXIV Classic from the code. Removed the Launcher Editor project as it is no longer needed (host file editing is cleaner). 2019-06-19 00:05:18 -04:00
Filip Maj
7587a6e142 Merge branch 'license_fix' into develop 2019-06-18 22:57:25 -04:00
Filip Maj
8940e65885 Changed the project name from "FFXIV Classic Server" to "Project Meteor Server" to avoid trademark issues. 2019-06-18 22:55:32 -04:00
Filip Maj
29ec6a9a88 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2019-06-17 23:29:34 -04:00
Filip Maj
3e26c491d4 Added license.md (see previous commit). 2019-06-17 23:28:44 -04:00
Filip Maj
9fd0e96b0e Added AGPL license to the whole codebase. All other devs who's code is in the project as of June 2019 came to agreement that they were fine to add this license to the project; Demo, Devi, Jorge, Azia, Shozokui, Dude22072. 2019-06-17 23:21:36 -04:00
Filip Maj
a9619a4b3c Fixed lobby packets not logging. 2019-06-17 23:08:48 -04:00
yogurt
8276c5c247 Merged in skeletonhorn/ffxiv-classic-server (pull request #64)
Add playanimation script
2019-06-12 14:41:19 +00:00
Yogurt
e9b3f4e51e Add playanimation script 2019-06-10 21:32:22 -07:00
yogurt
187d8300b0 Merged in skeletonhorn/ffxiv-classic-server (pull request #63)
Add packet flush when packet queue is full to Lobby and World servers
2019-06-10 15:59:32 +00:00
Yogurt
8da65938b7 Update ifrit appearance id to fix irit death animation 2019-06-09 17:21:21 -07:00
Yogurt
a92b558c88 Fix removing abilities from hotbar 2019-06-09 16:53:35 -07:00
Yogurt
57f3de66f8 Fix level 0 stuff 2019-06-09 15:34:31 -07:00
Yogurt
561114833c Add one more check to World Server. This should fix World breaking after
idling for a long time
2019-06-09 15:14:23 -07:00
Yogurt
324026874a Add packet flush when packet queue is full to Lobby and World servers 2019-06-08 23:02:49 -07:00
yogurt
dbdff59e0f Merged in skeletonhorn/ffxiv-classic-server (pull request #62)
Develop
2019-06-09 05:19:35 +00:00
Yogurt
a996797beb Level 0 class fixes
Add level 1 abilities when switching to level 0 class

Fix client error when switching to level 0 class
2019-06-08 21:44:06 -07:00
Yogurt
32330d557c Small command fixes
fix "You learn [command]." message not printing the name of the command
and enable message.

Make database save the short version of command id in hotbar table
2019-06-08 21:11:51 -07:00
yogurt
ec85cfd590 Merged in takhlaq/ffxiv-classic-server (pull request #61)
Combat changes and fixes.

Approved-by: Filip Maj <filipmaj@gmail.com>
2019-06-08 22:58:02 +00:00
Filip Maj
89c6191710 Added handling the "show text" param for emotes. 2019-06-08 17:37:14 -04:00
Filip Maj
eb43a7523d Forgot to commit TradeOfferCommand changes. Added removing the active ls if you are kicked/retired. 2019-06-08 17:28:09 -04:00
Filip Maj
f5ebb3fb3b Added caps and more checks for linkshells. 2019-06-08 17:06:10 -04:00
Filip Maj
8a03c40af9 Fixed linkshell invites being stackable. Fixed founder of a LS not being set to master. 2019-06-08 15:51:17 -04:00
Filip Maj
a07aa12783 Fixed new positions after realignment not saving. Fixed Dealer info not clearing from the db sometimes. 2019-06-08 14:46:19 -04:00
Filip Maj
e91960040c Fixed equip command breaking due to gearset referencing slot not actual item in slot. 2019-06-06 02:14:49 -04:00
Filip Maj
fea8638775 Changed id datatype for items to bigint. Removed bazaar and retainer inventories (now all in the characters_inventory table). Added server_items_dealing table for bazaar. 2019-06-06 01:50:15 -04:00
Filip Maj
c286df6a91 Cleaned up Bazaar deal/undeal scripts and disabled the check one due to an lockup. Needs lua rework to fix. 2019-06-06 01:45:06 -04:00
Filip Maj
3dcd9af6c0 Added "ToString" methods for Items, Packages, and Actors for easier debugging. Rewrote dealing code in InventoryItem as well as the WorldMaster. Rewrote how Bazaar and Retainer inventory is stored on the DB, merging all three tables into one. Removed a bunch of DB code due to the previous point. Random Item cleanup. 2019-06-06 01:43:27 -04:00
yogurt
4fbc388457 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #13)
Develop
2019-06-06 02:29:23 +00:00
Yogurt
f2e34174c4 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop
Fix Excruciate removign status from enemy rather than caster
2019-06-05 19:28:02 -07:00
yogurt
90078eb2e8 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #12)
Fix SLOT_OFFHAND conflict
2019-06-06 02:08:39 +00:00
Yogurt
7339e08172 Fix SLOT_OFFHAND conflict 2019-06-05 19:07:46 -07:00
yogurt
1fddfd50a6 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #11)
Develop
2019-06-06 02:06:19 +00:00
Yogurt
2e906ae090 Combat fixes and additions
Add default status gain and loss ids for status effects so buffs and
debuffs can have different ids.
Add sleep, slow, and slowcast

Fix sacred prism not slowing casts
Fix some incorrect text ids in battle commands
2019-06-05 18:57:21 -07:00
Yogurt
8ba3c195f2 Small fixes
Fix Shoulder Tackle script using Weaponskill function names
Change BattleNPC to not use array.Clone on respawn.
Move custom StatusEffect ids to 300000+ (will break these statuses until
new sql file is pushed)
2019-06-03 23:45:21 -07:00
Filip Maj
e96cc0c758 Minor edits to the previous commit. 2019-06-04 01:16:39 -04:00
Joseph Mikel Keller
2195b0b7dc Merged in dude22072/ffxiv-classic-server-1 (pull request #57)
Achievement Progress Request (0x0135) implementation
2019-06-04 05:11:51 +00:00
Filip Maj
ecf07317fc Inv/Equip load on first character fixed. 2019-06-04 00:41:02 -04:00
Filip Maj
69d4b19979 More inventory fixing after I broke it. Added preliminary final trade code. Moved recalc stats to the end of equipcommand, not on every modification of the referred item package. 2019-06-04 00:11:36 -04:00
yogurt
fdb767f155 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #10)
Push udpated traits db file
2019-06-03 00:35:30 +00:00
Yogurt
e1c86a4898 Push udpated traits db file 2019-06-02 17:33:05 -07:00
Filip Maj
88ff22e55e Added checks before creating the trade group so that a character couldn't be invited twice to trade. 2019-06-02 17:32:08 -04:00
Filip Maj
d49516c03e Added in "LinkedSlot" info in the InventoryItems. The slot sent when using "SendUpdateAsItemPackage" differ from a normal update. This was causing a crash. Checking is working again, trade is working up to the final transaction. 2019-06-02 17:11:14 -04:00
Filip Maj
42ee97d467 Refactored inventory to "ReferencedItemPackage" as this is a more general approach closer to what the FFXIV client uses. Added itempackage code to the LinkedItemList packets (also renamed from EquipmentList). Cleaned up trade code. 2019-06-02 16:57:46 -04:00
yogurt
8f92fde00e Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #9)
Combat fixes
2019-06-02 04:25:22 +00:00
Yogurt
3104478263 Combat fixes
Add actor update flag for hotbar to send hotbar changes all at once.
Add script for equipping all actions for a class/job.

Fix multiple script errors.
Fix multiple status flag errors
Fix battle command db errors
Fix error in spawnnpc and yolo.
2019-06-01 21:21:21 -07:00
Yogurt
a92ece58c1 Check for PreventMovement flag in BattleNpcController
Fix typos in some effect scripts
2019-06-01 03:39:46 -07:00
yogurt
6fcfd58b33 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #8)
Fix hiteffect.lua to not use bor since we can't reference other members of the same table
2019-06-01 10:20:19 +00:00
Yogurt
905cbf7d3c Add GetActionType for scripts.
Fix miss check for tp gain on attacks
2019-06-01 03:18:23 -07:00
Yogurt
4c850ea768 Don't generate TP on misses 2019-06-01 03:05:40 -07:00
Yogurt
afe1e59889 Fix hiteffect.lua to not use bor since we can't reference other members
of the same table

Change hp_penalty onGain and onLose to use the new function signature
2019-06-01 02:59:41 -07:00
yogurt
f3fe8c1de8 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #7)
Develop
2019-06-01 09:19:13 +00:00
Yogurt
4e054ca947 Add DoAction to raise so it at least plays the animation 2019-06-01 02:16:44 -07:00
Yogurt
eb949a8602 Move chimera abilities to Weaponskills 2019-06-01 02:14:21 -07:00
Yogurt
315452d121 Move shoulder tackle to abilities folder
Add Convert
2019-06-01 02:13:41 -07:00
Yogurt
1a9a8c2116 Fix wrong flag in esuna 2019-06-01 02:12:37 -07:00
Yogurt
97dcd765eb Add new hit effect flag for hit effects that only show animations
Fix SetMP setting MaxMP instead of MP

Fix substate updates not being sent
2019-06-01 02:10:40 -07:00
Yogurt
e00bb48386 Fix some incorrect CommandTypes in database 2019-06-01 00:57:31 -07:00
Yogurt
ef117204b3 Move raise in Teleport command so that it gets caught if isInn is true 2019-06-01 00:39:22 -07:00
Yogurt
9cda72f1ab Remove MP and TP before setting combo ids to actually take combo into
account for MP and TP cost
2019-05-31 23:42:52 -07:00
Yogurt
a99a129d9a Pass result container to effect script when effect times out 2019-05-31 23:34:37 -07:00
yogurt
6ae181fa0a Merged in skeletonhorn/ffxiv-classic-server-ai-fork/develop (pull request #6)
Update develop and pr combat changes to demo's fork
2019-05-30 06:33:30 +00:00
Yogurt
1f3c98312c Fix World getting stuck in group packet loop for real 2019-05-29 23:20:15 -07:00
Yogurt
db0aac3647 New database files for commands effects 2019-05-29 23:08:02 -07:00
Yogurt
00017468cc New scripts
New scripts for commands and effects that use the new function
signatures and work with the new statuseffectcontainer
2019-05-29 23:05:40 -07:00
Yogurt
4f80023156 Target flag and bug fixes
Add new flags for MainTarget's party, which allows for Protect to buff
other parties.

Fixed incorrect script function calls
Fixed bug causing World server to get stuck in a loop
2019-05-29 22:59:24 -07:00
Yogurt
6127ad44cc Pass BattleCommand to scripts. 2019-05-29 20:19:44 -07:00
Yogurt
d7c383d04a Use a static BattleCommand for auto attacks
This is temporary until all mob skills are added, including mob auto
attacks.
2019-05-29 20:06:31 -07:00
Yogurt
357805d04c Remove certain effects on class change 2019-05-29 19:57:36 -07:00
Yogurt
706a9fa721 Auto target self on skills whose main target can only be self. 2019-05-29 19:51:51 -07:00
Yogurt
289e4dc24b More targeting changes
Added CanUse instead of CanAttack/CanWeaponSkill/CanCast since they all
check the same things anyway.

Fixed some bugs like mp checking against hp in AddMP.
2019-05-29 19:46:29 -07:00
Yogurt
a458608322 BattleCommand changes
New targeting flags for BattleCommand and TargetFind. (This breaks
combat until new BattleCommand data is in)
Changed MP and TP to shorts in BattleCommand to handle cases where they
might go negative. (might not be correct?)
2019-05-29 19:24:58 -07:00
Yogurt
3e58cdbd6c Add SetTextId to CommandResult 2019-05-29 19:11:32 -07:00
Yogurt
3068a0c41b Add new functions for absorbs in CommandResultContainer 2019-05-29 19:10:05 -07:00
Yogurt
26ef649a6c Refactor StatusEffectContainer to better handle messages using
CommandResultContainer.

Alter Modifiers to be the same as ParamNames.

Add LoseOnClassChange flag for status effects.

Add a few missing status effects.

Fix EndTime for stance status effects to stop icon from blinking.
2019-05-27 23:05:20 -07:00
Yogurt
cc07e1f453 Pass BattleCommand to combat functions to prepare for passing
BattleCommand to scripts.

Add CommandResultContainer to status update to handle death from dots.
2019-05-27 17:31:25 -07:00
Yogurt
75c6708ac5 Handle dying in AddHP instead of OnDamageTaken. 2019-05-27 17:08:06 -07:00
Yogurt
ee1f4b0888 Fix base exp being off by 1 2019-05-27 16:56:15 -07:00
Yogurt
f6104812a5 Add ActionLanded to make some checks cleaner.
Split physical and magic text id dictionaries.

Add calculation for resists.
2019-05-27 16:52:56 -07:00
Yogurt
d0dca62a91 Add some helper methods for Modifier and only update stats for the
visual modifiers.
2019-05-27 16:26:10 -07:00
Yogurt
3b451849ae Initialize positionUpdates on Actor creation. 2019-05-27 15:45:06 -07:00
Yogurt
9889b6011b Move LookAt's same position check to the one that takes in an X and Y
position
2019-05-27 15:37:54 -07:00
Yogurt
9b566abb3d Add new HitEffect flags 2019-05-27 15:00:17 -07:00
Filip Maj
37cca32de8 Fixed equip script not changing graphics for various accessories. Added all item graphics to sql file except for some weapons and small clothes. 2019-05-20 11:58:43 -04:00
Filip Maj
02e1b8a82f Renamed the Inventory class file to ItemPackage (class was already renamed). Moved ItemPackage and Equipment classes to Character folder. Fixed unequip bug introduced by accidently removing InventoryBeginChangePacket. Added documentation to the Equipment class. Cleaned up Equipment packet code. 2019-05-12 16:16:44 -04:00
Filip Maj
267961233f Refactoring Equipment class. Fixed inital inventory setup due to missing addItem() (now addItems) function. Added Jorge's refactored Retainer manager script. 2019-05-12 15:03:34 -04:00
Filip Maj
d673670604 Fixed Issue #3 (Items are being shifted for linked items). Sending the updated equipment packet. 2019-05-08 13:18:53 -04:00
Filip Maj
b955c38a2a More GetInventory changes. 2019-05-06 16:43:39 -04:00
Filip Maj
044d7e5207 More changes. 2019-05-06 16:40:11 -04:00
Filip Maj
c1fdad2156 Changed scripts still referencing GetInventory to GetItemPackage. 2019-05-06 16:33:18 -04:00
Filip Maj
f038b525c6 Cleaning up imports. 2019-05-06 16:07:06 -04:00
Filip Maj
bcb609e4f6 Merge branch 'inventory_refactor' into develop
# Conflicts:
#	FFXIVClassic Map Server/Database.cs
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
#	FFXIVClassic Map Server/WorldManager.cs
#	FFXIVClassic Map Server/actors/area/Area.cs
#	FFXIVClassic Map Server/actors/area/Zone.cs
#	FFXIVClassic Map Server/actors/chara/Character.cs
#	FFXIVClassic Map Server/actors/chara/npc/Npc.cs
#	FFXIVClassic Map Server/actors/chara/player/Inventory.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
#	FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
#	FFXIVClassic Map Server/lua/LuaEngine.cs
#	FFXIVClassic Map Server/packets/send/Actor/AddActorPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/DeleteAllActorsPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatePacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatusAllPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/SetActorStatusPacket.cs
#	FFXIVClassic Map Server/packets/send/Actor/_0x132Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleAction.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX10Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultX00Packet.cs
#	FFXIVClassic Map Server/packets/send/Actor/events/SetEmoteEventCondition.cs
#	FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX08Packet.cs
#	data/scripts/commands/gm/giveitem.lua
2019-05-06 15:59:09 -04:00
Filip Maj
163f240cf9 Removed isExclusive as it is now loaded from gamedata. Cleaned up keys for retainer inventory. 2019-05-06 14:34:59 -04:00
Filip Maj
3066efeebb Cleanup the messy imports. 2019-05-06 13:39:24 -04:00
Filip Maj
10017b7e8c Cleaned up some warnings. 2019-05-04 20:53:08 -04:00
Filip Maj
1e4a1cf263 Merge branch 'ai-open' into develop
# Conflicts:
#	FFXIVClassic Lobby Server/Database.cs
#	FFXIVClassic Map Server/Database.cs
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
#	FFXIVClassic Map Server/actors/chara/player/Inventory.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
#	FFXIVClassic Map Server/dataobjects/Session.cs
#	FFXIVClassic World Server/Server.cs
2019-05-04 20:13:29 -04:00
Filip Maj
080f9ea23d Fixed bug where when a mob was insta-killed they would disappear (not die). More renames for action -> result. Reverted result packet unknown from 0x801 to 0x810. Added hitnum. Fixed isolation. 2019-05-04 18:53:00 -04:00
Filip Maj
e236e1d207 Renamed BattleActionPacket -> CommandResultPacket as it better defines what these packets do. A command fires -> here is what happened due to it. 2019-01-29 00:02:09 -05:00
Joseph Mikel Keller
1b69f5fc87 PacketProcessor.cs - Add in 0x0135 (Achievement Progress Request) 2018-10-25 04:39:00 +00:00
Joseph Mikel Keller
e4956edf50 AchievementProgressRequestPacket.cs- Create this 2018-10-25 04:37:41 +00:00
Joseph Mikel Keller
384d134f1d Database.cs - Add GetAchievementProgress 2018-10-25 04:35:12 +00:00
Joseph Mikel Keller
f361ee61cd Merged in dude22072/ffxiv-classic-server-2/dude22072/databasecs-getlatestachievements-chang-1540358175200 (pull request #56)
Database.cs - GetLatestAchievements - Change SQL query so it doesn't return incomplete achievements
2018-10-24 23:10:55 +00:00
Joseph Mikel Keller
7e6e51c6bf Merged in dude22072/ffxiv-classic-server-1/dude22072/gamedata_achievementssql-change-rewardp-1540356030506 (pull request #55)
gamedata_achievements.sql - change rewardPoints for Grand Company category to 0
2018-10-24 23:10:30 +00:00
Joseph Mikel Keller
5bdc760a5f Database.cs - GetLatestAchievements - Change SQL query so it doesn't return incomplete achievements 2018-10-24 05:16:17 +00:00
Joseph Mikel Keller
83ae7df6d9 gamedata_achievements.sql - change rewardPoints for Grand Company category to 0 2018-10-24 04:40:36 +00:00
Filip Maj
7c7742fb35 Update substate and implemented it into Character. Cleaned up more code mix. 2018-10-20 13:15:58 -04:00
Filip Maj
c55145d715 Added substate modifications to characters. 2018-10-20 13:02:14 -04:00
Filip Maj
42aa3d7512 Fixed some errors from the previous changes. 2018-10-20 12:31:24 -04:00
Filip Maj
07c467e1af Fixed JSON lib being broken from downgrade. 2018-10-20 12:16:34 -04:00
Filip Maj
bec0cae0eb Removed more dapper code and unsupported syntax. 2018-10-20 12:08:47 -04:00
Filip Maj
5bb3cc3b4e Cleaned up unused nuget packages. Downgraded JSON lib as the latest one has dependencies. Cleaned up some DB code using dapper (since it's deleted). 2018-10-08 15:31:41 -04:00
Filip Maj
d614ea6968 Rewrote code written in the new C# format to use older functions. Let's keep compatibility with older VS but also keep the code style consistent (already got enough inconsistencies). 2018-10-08 15:11:43 -04:00
yogurt
1579aa3d6a Bug fixes
Fixed LookAt resetting rotation when looking at self
Fixed BattleNpcs running to their target's exact position instead of the closest position they can attack from
2018-07-03 04:46:34 -05:00
yogurt
cf30eef39e AoE rewrite and bug fixes
Rewrote aoe checks for cone and line aoes and added minimum distance values
Added height checks for commands
Fixed combo effects repeating for every target hit by AoE attacks
Fixed teleport sometimes not raising (I think)
Fixed gear checks in some command scripts
2018-07-02 00:45:06 -05:00
yogurt
8c5375f609 Fixed a typo in blind's effect script 2018-06-25 23:44:04 -05:00
yogurt
c442dc9ecd Script fixes and new effects.
Cleaned up unneeded requires in some scripts
Fixed Second Wind
Added new effect scripts
Added bard song scripts that mostly work
2018-06-25 23:36:18 -05:00
yogurt
ace4dfe58f Small fixes
Fixed final message for multi-hit attacks.
Fixed self targeting for commands
Made it so player.lua doesn't skip over home points setting, just the quest setitng.
Began adding knockback effect handling
2018-06-25 18:20:20 -05:00
yogurt
79f2edf406 Bug fixes
Fixed some bugs with targeting flags
Fixed action equip bug for real this time
Fixed server crash when commands hit no targets
2018-05-31 11:25:55 -05:00
Filip Maj
0209f3e617 Added patching server web files. 2018-05-29 01:06:44 -04:00
Filip Maj
e799e8327f These should not have been here 2018-05-29 01:05:50 -04:00
yogurt
0f7e6f359d Added class-specific exp messages for non-english languages
Fixed status effect loss message not being sent
Fixed party bug where people in the same party were considered to be in different parties
2018-05-28 16:28:44 -05:00
yogurt
0739532c7d Reverting changes to characters_statuseffect sql file 2018-05-28 02:10:14 -05:00
yogurt
d23a84d6cf Undid change that broke parties 2018-05-27 23:02:08 -05:00
yogurt
8de606051a More bug fixes
Fixed loading status effects on login
Fixed barrage issues
Added untraited version of Protect
Added sanguine rite
2018-05-27 18:07:52 -05:00
yogurt
a7e59fa7e4 Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2018-05-27 15:17:00 -05:00
yogurt
922fb80f3d Bug fixes.
Added stoneskin effect to database.
Fixed Rampage not working
Fixed bug where abilities didn't equip correctly when leveling up
Added a temporary fix for returning while dead
Added handling for abilities that don't have an actiontype set, like elusive jump
2018-05-27 14:51:39 -05:00
yogurt
8c9f841d63 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/ai-open (pull request #5)
Combat Changes
2018-04-19 00:49:46 +00:00
yogurt
c5ce2ec771 Combat additions
Added formulas for base EXP gain and chain experience
Added basic scripts for most player abilities and effects
Added stat gains for some abilities
Changed status flags
Fixed bug with player death
Fixed bug where auto attacks didnt work when not locked on
Added traits
2018-04-18 16:06:41 -05:00
Filip Maj
0492bc4c59 Added compression code to packet. 2018-04-12 14:18:40 -04:00
Filip Maj
7abfbd5953 Forgot script. 2018-04-10 01:07:38 -04:00
Filip Maj
1d3dd99414 Got linkshell creation working. 2018-04-10 01:07:11 -04:00
Filip Maj
c3c19c3592 Fixed retainer script. 2018-04-07 18:19:56 -04:00
Filip Maj
a19517cce4 No longer need to do this as 0x131 is handled. Was crashing retainer. 2018-04-07 18:15:12 -04:00
Filip Maj
880b1f3066 Fixed the crash when class change is to a level 0 class. Now autosets to level 1. 2018-04-07 15:34:11 -04:00
Filip Maj
0b13b590a0 Renamed Inventory class to ItemPackage to reflect client naming. 2018-04-07 14:48:43 -04:00
Filip Maj
8aeaee1b19 SQL Files for new inventory. 2018-04-07 14:30:17 -04:00
Filip Maj
29e3f61b6b Fixed my lua fuckery some more. 2018-04-07 14:24:33 -04:00
Filip Maj
bbd4fcef3b Reversed all my lua fuckery. 2018-04-07 14:04:22 -04:00
Filip Maj
13727caf14 Database changes added. 2018-04-07 13:58:31 -04:00
Filip Maj
aba748cb5d Map Server Packet fix. 2018-04-07 13:50:43 -04:00
Filip Maj
611140568e Fixed broken KickEvent. Cleaned up Retainers to use the ItemPacakageUpdate packet. Fixed db references for retainer inventory. 2018-04-07 13:47:31 -04:00
Filip Maj
08dfd22bfa Removed the inventory lock stuff. 2018-04-07 13:47:09 -04:00
Filip Maj
5fd48fad6b Commited changed scripts. 2018-04-07 13:46:57 -04:00
Filip Maj
7e2246e8d8 If kickEvent is fired, the current event is popped. Commited Inventory changes. 2018-04-07 13:46:37 -04:00
Filip Maj
1e9d61c838 Fixed the refresh not sending inv change packets. 2018-04-07 13:45:05 -04:00
yogurt
b8d6a943aa Combat changes and bug fixes
Added the combo and proc systems
Added scripts for most weaponskill and spells as well as some abilities and status effects
Added support for multihit attacks
Added AbilityState for abilities
Added hiteffects that change based on an attack's parameters
Added positionals

Changed how targeting works for battlecommands

Fixed bug that occurred when moving or swapping hotbar commands
Fixed bug that occurred when losing status effects
2018-02-15 13:20:46 -06:00
CuriousJorge
f30360f245 Merged in CuriousJorge/ffxiv-classic-server/develop (pull request #50)
Actor script fixes, documented populace classes and misc things

Approved-by: Filip Maj <filipmaj@gmail.com>
2018-02-08 18:00:47 +00:00
CuriousJorge
359ea8a40e Actor script fixes, documented populace classes and misc things
Base
        - gcseals.lua
            Helper functions for GC seals.  Tables the seal caps per rank and checks against it when adding seals.

    Commands
        - PartyTargetCommand.lua :
            Handles markers above head.  Basic documentation, only works on self. "Heart" doesn't work, client bug?
            Eventually will need an object in the party class to handle tracking marked players/targets for the group.

    Class Scripts
        - PopulaceCaravanAdviser.lua
            Documented.  Can purchase gysahl greens from them, unsure what else their use is.
        - PopulaceCaravanGuide.lua
            Documented the Caravan Guide NPC, who escorts the chocobos with you.
        - PopulaceCaravanManager.lua
            NPC who handles signing up for Caravan escort, among other functions.
        - PopulaceSpecialEventCryer.lua
            Covers three NPCs for the Foundation Event.  They handle trading specific items in exchange for GC seals.

    Unique ID Script fixes
        - flame_private_sisimuza_tetemuza.lua
            Foundation Event NPC functions laid out.
        - flame_sergeant_mimio_mio.lua
            Foundation Event NPC functions laid out.
        - serpent_lieutenant_marette.lua
            Foundation Event NPC functions laid out.
        - serpent_private_tristelle.lua
            Foundation Event NPC functions laid out.
        - serpent_sergeant_frilaix.lua
            Foundation Event NPC functions laid out.
        - serpent_sergeant_nelhah.lua
            Removed unique script. PopulaceSpecialEventCryer handles it.
        - ansgor.lua
            Had incorrect defaultTalk value
        - ne_of_eshtaimes.lua
            Door @ !warp 209 -139 206.113 195   Had incorrect mapObj value.
2017-12-13 15:09:10 -05:00
Filip Maj
127ac15936 Fixed bazaar flags for seek item. Finished seek item trading. 2017-12-10 23:52:10 -05:00
Filip Maj
0cb2fe1a68 Added bazaar scripts and missing class file. 2017-12-10 22:54:47 -05:00
Filip Maj
c0312079ef Added broadcast packet list to Player. Fixed bazaar flags not working. Added the seeking item trade code. 2017-12-10 22:53:37 -05:00
Filip Maj
a9d4e621e3 Events are now pushed onto a stack and popped off. Turns out multiple events *CAN* happen. Fixed quantity bugs when saving to DB. Fixed buying stacks. 2017-12-10 22:32:24 -05:00
Filip Maj
08c5980b22 Moved SendItemPackage to character class. Added a flag check after a bazaar purchase is made. Discovered a flag in InventoryBeginChangePacket that either modifies the client package or clears and refills it. Implemented this mode for a bunch of "SendFullInventory" methods. 2017-12-10 15:13:33 -05:00
Filip Maj
f5ea82f735 Added the UpdateItemPackage packet used to signal the server to send bazaar item info. Added a transaction method in WorldManager. Fixed some inventory bugs. InvItems now track what player, itempackage, and itemslot they are in... and may have their quantity set from there. Fixed DB SetQuantity bug. 2017-12-10 13:38:53 -05:00
Tahir Akhlaq
81c97105b7 Merge branch 'ai-open' of https://bitbucket.org/skeletonhorn/ffxiv-classic-server-ai-fork into ai 2017-12-10 15:21:37 +00:00
yogurt
837c7a9223 Health updating fix, temp r0 fix 2017-12-10 09:20:42 -06:00
Tahir Akhlaq
cd60c571ac Merge branch 'ai-open' of https://bitbucket.org/skeletonhorn/ffxiv-classic-server-ai-fork into ai
# Conflicts:
#	data/scripts/modifiers.lua
2017-12-10 15:07:28 +00:00
yogurt
205d3619d6 Merging 2017-12-08 02:08:13 -06:00
yogurt
1275c8b5da Added party to Gridania opening, fixed BattleActionx18 and made it so x18 is used for packets with more than 10 targets. Changed how death works. Added respawn time and roam modifiers. Added TryAggro functions and moved aggroing out of roaming and helpplayers. Fixed high cpu usage in zone's OnUpdate function. Fixed work value in player update 2017-12-08 00:58:39 -06:00
Filip Maj
b2e273d7cf Finished fixing bugs in the bazaar code. 2017-12-04 22:58:18 -05:00
Filip Maj
88233cf6d2 Fixed error, removed RabbitMQ package as it isn't used. 2017-11-17 17:03:47 -05:00
Filip Maj
05eca7f22e Fixed bad merge. 2017-11-17 16:51:35 -05:00
Filip Maj
7a02d38e94 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop
# Conflicts:
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
2017-11-17 15:14:58 -05:00
Filip Maj
af121f52bd Added packets for various search things Showmo found. 2017-11-17 15:13:38 -05:00
Filip Maj
e8c9904e1d More refactoring. Adding to bazaar now works for selling and seeking by gil. 2017-11-11 17:05:07 -05:00
Filip Maj
bbac4b0fce Renamed Type7Param to ItemRefParam. Changed a lot of "inventoryType" names to "itemPackage". Moved inventory code to Character class for easier use and auto-choosing the correct package. 2017-11-11 13:46:12 -05:00
Filip Maj
3850860440 Added seek nameplate code. Added bazaar transaction stuff to WorldManager and DB. Added Item Gamedata to InventoryItem class. 2017-11-11 10:56:15 -05:00
Tahir Akhlaq
bb31bb0f23 Merge branch 'ai-open' of https://bitbucket.org/skeletonhorn/ffxiv-classic-server-ai-fork into ai 2017-11-09 11:52:20 +00:00
Filip Maj
b191da416b Modified ItemWasteCommand so it uses the given itempackage. This lets you discard loot. 2017-10-21 13:09:04 -04:00
Filip Maj
2a489953db Added the skeletons of the rest of the item commands. 2017-10-21 13:01:14 -04:00
Filip Maj
fe4b9cb2bf Added more helper methods and constants for inventory item. 2017-10-21 11:29:28 -04:00
Filip Maj
95b003cc2b More inventory item refactoring. 2017-10-15 23:56:04 -04:00
Tahir Akhlaq
27200b8df5 moved ally engage stuff to ContentArea onUpdate 2017-10-11 19:23:40 +01:00
Tahir Akhlaq
520ae7a119 added helpers for DoW/DoM/DoH/DoH
- fixed allies not being able to aggro on roam
- fixed static characters aggroing
2017-10-11 15:02:12 +01:00
yogurt
460722d3d5 Opening changes 2017-10-11 06:42:06 -05:00
yogurt
92de857cda opening quest stuff 2017-10-10 13:32:47 -05:00
CuriousJorge
4323eb5385 Merged in CuriousJorge/ffxiv-classic-server/develop (pull request #49)
Inventory fixes + Scripts added

Approved-by: Filip Maj <filipmaj@gmail.com>
2017-10-10 14:14:08 +00:00
CuriousJorge
324ebab2d2 Inventory.cs - GetItemQuantity() added
- AddItem functions to cast INV_ERROR to INT for LUA
             - Fixed unique item check.  It was checking for Rare flag, not EX

Scripts :
        Base
            - shop.lua  : Functions for buying/selling from a variety of shop scripts

        Commands
            - EmoteStandardCommand.lua fixed not being able to use emotes when sitting
            - DiceCommand.lua fixed.  No arguments sets default value of 100 as per the ingame description.
                                      Max value raised from 999 to 1000.

        GM Commands
            - speed.lua fixed when using single argument
            - nudge.lua fixed sanitizing.  Made arguments reversible to allow !nudge up 10 & !nudge 10 up
            - giveitem.lua added inv_error handling.  Need to do to rest of item commands at some point
            - givecurrency.lua changed to have you enter a regex'd name of item rather than item ID.
                               Eg. "!givecurrency fire_crystal 10". Added inv_error handling to it.
            - warpplayer.lua added.  Moves yourself to name of player, or moves first player to second player
            - warpid.lua added. For warping to the first instance of an actor's uniqueId the server comes across.
            - quest.lua added.  For adding/adjusting quests for debugging them.

        Class Scripts
            - PopulaceBlackMarketeer.lua updated to utilize shop.lua
            - PopulaceShopSalesman.lua updated to utilize shop.lua
            - PopulaceCompanyShop.lua updated to utilize shop.lua
            - PopulaceCompanyBuffer.lua added and documented along with menu layout.  Needs working status effect to finish.
            - PopulaceCompanyGLPublisher.lua added.  Mostly documented, barely functional.
            - PopulaceCompanyGuide.lua added. Documented, fully functional.
            - PopulaceCompanyOfficer.lua added. Documented.  Menus work.  Needs GC rank table at some point
                                                for documenting GC ranks/seal caps.
            - PopulaceCompanySupply.lua added and mostly documented.  Read-only basic menu flow, static LUA tables
                                         used to set it up, will need SQL tables at some point to replace them with.
                                         Some guesswork on what menus show since no video reference could be found.
            - PopulaceGuildShop.lua updated. Mostly documented.  Read-only shop menus.
2017-10-09 23:40:38 -04:00
CuriousJorge
5ccc2435b0 Merged Ioncannon/ffxiv-classic-server into master 2017-10-09 21:11:07 -04:00
Tahir Akhlaq
13708a2361 apparently i forgot to push modifiers script 2017-10-09 21:15:43 +01:00
Filip Maj
59e3b2379a Implemented mode trade methods. Figured out the modifiers portion of the item packet and rewrote how they are stored. 2017-10-08 12:26:22 -04:00
yogurt
9fc99faa5c Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2017-10-06 20:45:36 -05:00
yogurt
116a573f85 Save class/level parameter save info on level up 2017-10-06 20:45:10 -05:00
Tahir Akhlaq
a0c4d80c5e broken attempt at opening quest director combat 2017-10-05 18:37:51 +01:00
Filip Maj
8ae4fbc045 Forgot project file. 2017-10-05 13:31:15 -04:00
Filip Maj
e819603432 Added new search packets. 2017-10-04 10:25:16 -04:00
Tahir Akhlaq
bab81a809c fixed auto attack (<3 showmo) 2017-10-03 07:32:32 +01:00
Filip Maj
441c1a6383 Implemented countdowns. 2017-10-01 12:39:46 -04:00
Filip Maj
58334a0e5f Implemented newly discovered packets (Dalamud, Countdown). 2017-10-01 12:31:45 -04:00
Filip Maj
94491903f7 More trade work. 2017-10-01 12:23:54 -04:00
yogurt
f3a823af03 Only send current class's exp on login. Exp now updates on class change 2017-09-30 20:04:45 -05:00
yogurt
5dfbc0f249 EXP and levels now get saved and loaded from database, changed battlecommand id dictionary to hold lists to account for archer and DoH/DoLs getting multiple abilities at certain levels. Level 1 abilities are now added to the hotbar on character creation. 2017-09-30 07:28:08 -05:00
yogurt
ab98f3662f Removed old EquipAbility function from player.cs 2017-09-27 18:12:02 -05:00
yogurt
33f8709d76 Added exp and leveling functions, redid equip ability functions to allow adding abilities that aren't for the player's current class and made functions more clear, added dictionary of BattleCommand ids indexed by a tuple containing classId and level. 2017-09-27 18:10:22 -05:00
Tahir Akhlaq
56491266cc another attempt to get opening fight working (client hangs after talking to yda for second time for some reason..) 2017-09-22 03:26:12 +01:00
Filip Maj
c7e38b8b00 Implemented trade invitation code. 2017-09-17 15:04:29 -04:00
Filip Maj
9649d755a9 Fixed a bug in inventories. If no null gap was found endOfListIndex would go to -1. 2017-09-16 13:57:16 -04:00
Filip Maj
e581727625 Added errors to AddItem so a script writer knows if the inventory was full or not. 2017-09-16 13:28:37 -04:00
Filip Maj
06e0c32062 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2017-09-16 13:19:50 -04:00
Filip Maj
77203bca4c Fixed multiparams not being returned on CallClientFunction(). Was due to bad merge. Added Jorge's scripts. 2017-09-16 13:19:41 -04:00
Filip Maj
7b1f95cd77 Fixed multiparams not being returned on CallClientFunction(). Was due to bad merge. Added Jorge's scripts. 2017-09-16 13:19:10 -04:00
Tahir Akhlaq
ba8184db89 attempt to add tutorial fight
- added tempvars which are reset on spawning/zoning
2017-09-16 02:50:32 +01:00
Tahir Akhlaq
da621dfc0e added pool/spawn/genus mod loading
- moved ai helper classes to own folder
2017-09-12 01:24:02 +01:00
Tahir Akhlaq
ce5030acd1 added mob name colour update
- added mobmods (need to be loaded from db)
- added Zone.GetBattleNpcById
- added missing IsValidTarget check in AttackState
2017-09-10 03:44:12 +01:00
Filip Maj
a309e651da Fixed issues Jorge found. 2017-09-09 16:30:29 -04:00
Filip Maj
16e99040e0 Forgot Retainers_Inventory sql file. 2017-09-09 14:34:44 -04:00
Filip Maj
3f82ca1244 Added Retainer actor classes and some new spawns. 2017-09-09 14:34:04 -04:00
Filip Maj
8f487689ba Pushed new db schema for inventory and retainers. 2017-09-09 14:32:08 -04:00
Filip Maj
b092d447cc Retainer name was not set. 2017-09-09 14:28:02 -04:00
Filip Maj
4160622556 Scripts for retainers. Adds item storage functionality. 2017-09-09 14:12:38 -04:00
Filip Maj
64006d2351 Added retainer inventory code. Renamed CURRENCY inv type to CURRENCY_CRYSTALS so I don't forget. 2017-09-09 14:11:35 -04:00
Filip Maj
52c707d66e More cleanup. 2017-09-09 12:42:00 -04:00
Filip Maj
9174801fdb Moved all DB update code into it's own method. 2017-09-09 12:37:24 -04:00
Filip Maj
9529a1374e Merge branch 'inventory_overhaul' into retainers 2017-09-09 12:21:51 -04:00
Filip Maj
8755ca4f33 Fixed a bunch of SQL errors. Added checks for quality so a remove command didn't take out items regardless of quality. Fixed errors. 2017-09-09 12:21:37 -04:00
Filip Maj
a14e36fadc Bad old SQL line was adding exponentially increasing duplicates. 2017-09-09 11:33:23 -04:00
Filip Maj
bc95c139de Implement DB updates for player. Cleaned up DB calls. No longer track slot, it's ordered by index id (no concept of slots anyway in client). 2017-09-09 11:25:58 -04:00
Filip Maj
40ad1d8a29 Figured out and implemented the Retainer scripts. 2017-09-09 10:56:11 -04:00
Filip Maj
76f073d85f Got retainer meeting group working and cleaned up retainer instancing. Added a RemoveItemAtSlot with quantity. 2017-09-09 10:54:40 -04:00
yogurt
9077c60b96 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/ai-open (pull request #4)
Minor changes to fix equipability bugs
2017-09-08 14:22:41 +00:00
Tahir Akhlaq
645a1fb4fb fixed mob loading from db
- todo: see todos in code (all 169 of them)
2017-09-07 22:02:02 +01:00
Tahir Akhlaq
7c30b95c4b added some breakpoints to try figure out why mobs arent spawning
- fixed spawn table
2017-09-06 00:28:49 +01:00
Tahir Akhlaq
2bfaf376ef moved battlenpc loading to db (still doesnt load for some reason) 2017-09-05 23:32:57 +01:00
Tahir Akhlaq
68a2d5f0b9 stubbed item use state (needs to actually look up the item and get its reuse stuff)
- added tables to load mobs from (probably dont import besides server_battlenpc_genus.sql)
- added field to server_battle_commands for commands usable by both monsters and players (probably arent any really)
2017-09-05 21:03:38 +01:00
Filip Maj
5bec522c8e Fixed bugs in the new inventory code. 2017-09-05 15:35:33 -04:00
Filip Maj
81d82cd7a8 Rewrote the inventory code, splitting the packet updates from the list updates. 2017-09-05 14:44:06 -04:00
Filip Maj
f437b36f5a Started implementing retainers. Added a instanced retainer spawn. Documented retainer scripts. 2017-09-05 12:37:23 -04:00
Filip Maj
b5054debea Added first set of item search packets. 2017-09-03 17:02:08 -04:00
Filip Maj
4e39b082f1 Added new scripts, implemented some old ones. 2017-09-03 16:44:10 -04:00
Filip Maj
62484e2f87 Fixed the retainer database error. Loading code now matches the new retainer db schema. 2017-09-03 16:37:05 -04:00
yogurt
50b4f517f2 Fix FindFirstCommandSlotById to be able to find empty slots again 2017-09-03 11:18:35 -05:00
yogurt
2b5a6997f4 Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2017-09-02 22:41:02 -05:00
Tahir Akhlaq
4978813c27 fixed death/despawning kinda (need to figure out why hp wont tick down after respawning) 2017-09-03 01:01:19 +01:00
yogurt
6e1983031b Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2017-09-02 10:25:17 -05:00
Tahir Akhlaq
c5cc7c2f00 fixed auto attack messing up cast anim
- fixed auto attack anim for mobs (<3 u ion)
- added hotbar timer updates (<3 u azia)
- fixed actor block bug
- cleaned up substate retardation
- fixed some targetfind issues
- added despawn state
- added messages for in progress commands
- added fields for aoe target, range, battleAnimation to server_battle_commands table
2017-08-31 06:01:26 +01:00
Filip Maj
4762811347 Fixed global.lua be screwed up by merge. 2017-08-30 19:43:20 -04:00
yogurt
c55acba1b6 Changed primary key for characters_hotbar.sql and removed id column. 2017-08-30 16:26:28 -05:00
Filip Maj
4c7928da78 Fixed screwed up cast animation. 2017-08-29 22:27:32 -04:00
Tahir Akhlaq
517bdc0638 fixed cast interrupt
- dont allow targeting of mob moving back to spawn
2017-08-30 00:14:14 +01:00
yogurt
2cee5ff573 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/ai-open (pull request #3)
EquipAbility refactor
2017-08-29 14:59:29 +00:00
yogurt
c3fd8f917e Added UnequipAbility function, made EquipAbility work with zero indexed hotbar database, added new checks to EquipAbilityCommand.lua 2017-08-29 09:00:09 -05:00
Filip Maj
91afda04ca Added interrupt animation. 2017-08-29 00:52:57 -04:00
Filip Maj
e60da4f7b4 Wasn't actually sending packets. Changed casting animation back and moved castbar removal to cleanup. 2017-08-29 00:38:07 -04:00
Filip Maj
67485eafc0 Fixed infinite loop with DoBattleAction. Added some casting logic. 2017-08-29 00:33:23 -04:00
Filip Maj
d81832f256 Cleaned up hotbar database stuff (slot starts at 0 now!) and fixed a few bugs in the state system. 2017-08-28 23:21:21 -04:00
Filip Maj
7ad40f625a Refactored Demo's battle action code and cleaned things up. 2017-08-28 21:45:01 -04:00
Filip Maj
71d5bbc9ff Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2017-08-28 20:26:27 -04:00
Filip Maj
37b8203dae Rewrote the BattleActionPacket classes to standardize them. Added a method in Character.cs to fire off BattleActions. 2017-08-28 20:26:21 -04:00
Tahir Akhlaq
f4016e1a12 renamed tables for consistency
- added magic.lua (todo: enumerate modifiers and stuff)
- moved aggro handling to session position update
- some cleanup
2017-08-29 01:15:12 +01:00
Tahir Akhlaq
6c74222b68 renamed ability to battlecommand
- moved spells to scripts/commands/
- added aoe range field to battle_commands.sql
- changed AttackState to use character's onAttack
2017-08-28 05:20:00 +01:00
Filip Maj
7e4fc52b9e Some extra documentation for the Parley script. 2017-08-26 17:04:36 -04:00
Filip Maj
e5a9658b5a Added Parley code to experiment with. 2017-08-26 16:59:15 -04:00
Tahir Akhlaq
6f5a480cbd Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into ai
# Conflicts:
#	FFXIVClassic Map Server/Database.cs
#	FFXIVClassic Map Server/WorldManager.cs
#	FFXIVClassic Map Server/actors/area/Area.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
2017-08-26 20:17:16 +01:00
Filip Maj
ce2d22d984 Added sellprice assignment to ItemData.cs. Forgot it! 2017-08-26 14:24:39 -04:00
Filip Maj
52da0a671f Updated method names of "RemoveItem" as Lua hates overloads. 2017-08-26 14:21:54 -04:00
Filip Maj
afe79e6c5f Set version number to v0.1. 2017-08-26 14:00:40 -04:00
Joseph Mikel Keller
d757ad39fc Merged in dude22072/ffxiv-classic-server-1/develop (pull request #47)
Fixed the "pretty borders" inconsistency.

Approved-by: Tahir Akhlaq <xdemolish@hotmail.com>
2017-08-26 17:59:14 +00:00
Filip Maj
74ce5a2fe1 Merge branch 'master' into develop
# Conflicts:
#	FFXIVClassic Lobby Server/FFXIVClassic Lobby Server.csproj
#	FFXIVClassic Map Server/Database.cs
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
#	FFXIVClassic Map Server/PacketProcessor.cs
#	FFXIVClassic Map Server/WorldManager.cs
#	FFXIVClassic Map Server/actors/Actor.cs
#	FFXIVClassic Map Server/actors/area/Area.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
#	FFXIVClassic Map Server/lua/LuaPlayer.cs
#	data/scripts/base/chara/npc/populace/PopulaceChocoboLender.lua
#	data/scripts/commands/gm/speed.lua
#	data/scripts/commands/gm/warp.lua
#	data/scripts/global.lua
#	data/scripts/player.lua
#	data/scripts/unique/fst0Town01a/PopulaceStandard/khuma_moshroca.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/ahldskyf.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/angry_river.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/ansgor.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/arnegis.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/arthurioux.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/astrid.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/audaine.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/bango_zango.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/bayard.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/bloemerl.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/bmallpa.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/bnhapla.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/chichiroon.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/drowsy-eyed_adventurer.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/eugennoix.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/fickle_beggar.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/hob.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/ivan.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/maetistym.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/mharelak.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/muscle-bound_deckhand.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/pasty-faced_adventurer.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/pearly-toothed_porter.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/ptahjha.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/suspicious-looking_traveler.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/syhrdaeg.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/syngsmyd.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/tatasako.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/tefh_moshroca.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/thata_khamazom.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/thosinbaen.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/tittering_traveler.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/totoruto.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/triaine.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/trinne.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/unconscious_adventurer.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/undsatz.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/vhynho.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/waekbyrt.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/whahtoa.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/wyra_khamazom.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/wyrstmann.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/xavalien.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/zonggo.lua
#	data/scripts/unique/sea0Town01a/PopulaceStandard/zuzule.lua
#	sql/server_zones_spawnlocations.sql
2017-08-26 13:53:23 -04:00
Filip Maj
3b271980cc Added more Ul'dah scripts. Start location fix now only happens in correct zones. 2017-08-26 13:11:25 -04:00
Tahir Akhlaq
922f3ccd1e Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into ai
# Conflicts:
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
#	FFXIVClassic Map Server/lua/LuaEngine.cs
2017-08-26 18:04:31 +01:00
Tahir Akhlaq
c070f5b80e added ion's and showmo's enums
- added nullable DateTime param to UnixTimeStampUTC
2017-08-26 17:46:45 +01:00
Filip Maj
ff93dc41ef Added casting bar functions. 2017-08-26 12:33:37 -04:00
Filip Maj
546908acde Some fixes and missing scripts. 2017-08-26 10:23:13 -04:00
Tahir Akhlaq
1ae15df64c add ion's fix for BattleActionX10Packet crashing client
- add blizzara spell lua
2017-08-26 06:47:07 +01:00
Tahir Akhlaq
9024f3fad6 cleaned up magicstate and weaponskillstate
- todo: fix IsFacing
- added thunder spell (todo: figure out why battleactionx10 crashes client on sending shit)
2017-08-26 04:08:26 +01:00
Tahir Akhlaq
452f1cc8c0 fixed some paths in project 2017-08-25 05:12:10 +01:00
Tahir Akhlaq
11bbb023d9 abilities now use correct animation id (<3 azia)
- did stuff with magicstate/attackstate
- fixed status effect tick
- added regen status (todo: actually populate the table and use that name instead of enum's)
- added baseStats to char (todo: add bonuses and stuff on top of those, set charaWork values to the calculated ones + bonus)
2017-08-25 03:52:43 +01:00
Tahir Akhlaq
88abd59ec3 fixed auto attacking self/npcs 2017-08-24 16:36:56 +01:00
Tahir Akhlaq
5e2487c8cc missed a file from previous commit 2017-08-24 05:36:12 +01:00
Tahir Akhlaq
9bb298b2f3 added modifier class
- added auto attack animation (<3 showmoltti)
- added thing to send battle packet from lua
2017-08-24 05:12:30 +01:00
Tahir Akhlaq
cbbfa4ed95 fixed mobs not pathing
- fixed roaming (todo: should probably move to attackstate too or something)
2017-08-23 19:31:03 +01:00
Tahir Akhlaq
54af893570 add some more locks, fixed typo in AddHP, add missing ability 2017-08-23 03:22:17 +01:00
yogurt
c79b5c9992 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/ai-open (pull request #2)
Ai open
2017-08-22 20:17:50 +00:00
yogurt
e390138258 Removed unneeded recast timer parameter in EquipAbility call in EquipAbilityCommand.lua 2017-08-22 14:56:57 -05:00
yogurt
35f9251056 Split update hotbar function into seperate command and recast functions, fixed recast packet spam, recast timers now reset when commands are added to the hotbar and when changing classes, and are now saved in the databse correctly and sent on login. Merged demo's changes. 2017-08-22 14:50:53 -05:00
Tahir Akhlaq
86bf0eec81 filled out abilities table (todo: range needs correcting)
- changed target find stuff to use windower's (need to check it actually works..)
2017-08-22 19:57:52 +01:00
Tahir Akhlaq
ebd295bfa4 add abilities table 2017-08-21 03:37:35 +01:00
Tahir Akhlaq
a89fc64555 fix crash in gm command thing, commit stupid shit i havent figured out yet 2017-08-21 00:40:41 +01:00
Tahir Akhlaq
1856cc0634 (badly) ported dsp's pathfind code
- added distance for vectors
- todo: why does it go retard
2017-08-16 17:25:32 +01:00
Tahir Akhlaq
68657e1edc stubbed some more states
- stubbed some ability stuff
- moved packet things to loop instead of session only
- added mob roaming and aggro
- todo: fix target find/detection/pathfinding speed/line of sight/line aoe length etc
- todo: see "// todo:" in code
2017-08-02 23:09:04 +01:00
Tahir Akhlaq
c7b87c0d89 effect timers now display (<3 ion)
- added source/target to effects
- todo: send battle packet crap
2017-07-27 22:19:20 +01:00
Tahir Akhlaq
8bebba64b3 fixed some timers
- status icons now display (<3 u ion)
- todo: populate status tables, figure out why effect wont tick down for me
2017-07-27 03:58:42 +01:00
Tahir Akhlaq
ddad27a5f9 fixed high cpu usage caused by spawning stupid amounts of script objects each tick 2017-07-18 04:54:05 +01:00
Tahir Akhlaq
53207a9ff0 added status effect saving
- added some of the packets to add/remove effects (todo: battle packet too)
2017-07-18 00:55:03 +01:00
Tahir Akhlaq
d9d185d7e6 added status effect loading
- todo: populate table (and test this doesnt break everything ever), send charawork and message packets
2017-07-15 22:11:22 +01:00
Tahir Akhlaq
13af16ec0e Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai
shitty line ending conflicts
# Conflicts:
#	FFXIVClassic Map Server/lua/LuaEngine.cs
2017-07-12 18:48:44 +01:00
Tahir Akhlaq
f4687942af stubbed some more stuff, forgot to pass args to function 2017-07-12 18:46:39 +01:00
Tahir Akhlaq
7c08420206 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into ai 2017-07-11 20:52:43 +01:00
yogurt
3734f22fc2 Merged in skeletonhorn/ffxiv-classic-server-ai-fork/ai-open (pull request #1)
equip ability functions
2017-07-11 19:52:04 +00:00
Tahir Akhlaq
7ab40a30f1 stubbed some more functions 2017-07-11 20:49:38 +01:00
yogurt
4032258e76 More merge fixes! 2017-07-11 11:52:54 -05:00
yogurt
4dee26e136 Fixing more merge errors. I'm bad at this 2017-07-11 09:50:54 -05:00
yogurt
86a2e4aff3 Fixing merge error 2017-07-11 09:45:11 -05:00
yogurt
b2e86d282a Merge branch 'ai-open' of https://bitbucket.org/takhlaq/ffxiv-classic-server into ai-open 2017-07-11 09:40:10 -05:00
yogurt
efdec5e472 Add equip ability functions
Fix EquipAbility SQL query
2017-07-11 09:08:50 -05:00
Tahir Akhlaq
84d5eee1fc cleaned targetfind some
- added character allegiance types
2017-07-11 01:54:15 +01:00
Tahir Akhlaq
59fab08230 added some more targetfind stuff to handle pets (needs testing) 2017-07-10 23:52:31 +01:00
Tahir Akhlaq
1637bba167 added target finding within box (thanks kjLotus!)
- added function to return position as Vector3 to Actor (todo: maybe we should just use the class instead of 3 separate floats?)
- added function to return all actors in Area
- actually added documentation to TargetFind stuff (kill me pls)
- todo: actually test this..
2017-07-10 02:31:37 +01:00
Filip Maj
372d50d7eb Added closed doors to the two private areas for the ul'dah opening. CAN'T ESCAPE NOW!!!! 2017-07-09 19:13:17 -04:00
Filip Maj
bac901c437 Added warp after the ul'dah battle to the private area. 2017-07-09 18:49:12 -04:00
Filip Maj
69f7fb5e47 Ported over all the opening directors and improved the director code a bit more. Also implemented content instances for Grid/Uld. 2017-07-09 18:38:01 -04:00
Filip Maj
24c46c0480 Fixed issue where any actor < -1000 Z position would appear anyways. 2017-07-09 12:58:22 -04:00
Filip Maj
affff96837 A default return destination is now set on new character based on initialTown. 2017-07-09 11:40:28 -04:00
Filip Maj
77d6cb2e43 Fixed up how "special" items work (ie: PUG and ARC weapons). No more glitches hopefully. 2017-07-09 11:39:17 -04:00
Tahir Akhlaq
4ed8f3e5e2 added a bit of targetfind stuff 2017-07-09 00:27:15 +01:00
Tahir Akhlaq
c55c0b327d forgot to fix this on conflict resolving 2017-07-08 04:53:06 +01:00
Tahir Akhlaq
4695193aa0 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into ai
# Conflicts:
#	FFXIVClassic Map Server/actors/Actor.cs
#	FFXIVClassic Map Server/dataobjects/Session.cs
#	FFXIVClassic Map Server/lua/LuaEngine.cs
2017-07-08 04:10:36 +01:00
Tahir Akhlaq
247b5ca709 missed some files from previous commit 2017-07-08 00:20:55 +01:00
Tahir Akhlaq
d895357182 renamed mob stuff to battlenpc
- stubbed spawn/die/despawn functions
2017-07-07 22:08:48 +01:00
dude22072
5a5c0a3a5f Fixed the "pretty borders" inconsistency. 2017-07-06 22:30:03 -05:00
Filip Maj
caf254fd95 More old test code removed. 2017-07-06 22:11:14 -04:00
Filip Maj
151756329c Removed oooold test code. 2017-07-06 22:10:19 -04:00
Filip Maj
ddfc71d3af GLWarpPoint shows current difficulty now too. Added some test stuff to the Orb/Sweep directors. 2017-07-06 22:09:03 -04:00
Filip Maj
a77a90578f Merge branch 'packet_actortarget_rewrite' into guildleve
# Conflicts:
#	FFXIVClassic Lobby Server/packets/send/SelectCharacterConfirmPacket.cs
2017-07-06 22:02:14 -04:00
Filip Maj
8c95543f6d Missing lobby packet???? 2017-07-06 21:59:29 -04:00
Filip Maj
5dff4cbdd3 Fixed bug with Broadcast Packet. Was adding player to the instance list while it shouldn't have been, and designed BroadcastPacket assuming so. Cleaned it all up and fixed, so now emote work after warp. Fixed Chocobo packets so correct appearance will show when player is spawned while riding gobbue. 2017-07-06 21:59:12 -04:00
Tahir Akhlaq
cc1929a9fb moved getpath crap to pathfinding (or should i keep it in actor?)
- stubbed some more crap
2017-07-02 20:01:24 +01:00
Tahir Akhlaq
100f3ae156 fixed an issue causing client to crash 2017-07-01 02:52:05 +01:00
Tahir Akhlaq
e56238a10c fixed crash on updating controller for npcs
- fixed updating player movement
2017-06-30 04:30:36 +01:00
Tahir Akhlaq
62055eff04 stubbed some more functions from kj's ai stuff
- fixed some typos
- cleaned some debug code
2017-06-29 21:54:30 +01:00
Tahir Akhlaq
6b023ceb3c added a status effect container
- added status effect container to mobs and player objects (maybe should add to all Characters?)
- todo: handle gain/tick/lose in lua, send packets, everything else
2017-06-29 19:14:07 +01:00
Tahir Akhlaq
637f7f3d95 added status effect class
- todo: load info into effects
- todo: create a container, call onGain/onLose/onTick for effects etc
2017-06-29 19:14:06 +01:00
Tahir Akhlaq
c162fb0eab added super basic hate container class which doesnt actually do anything yet 2017-06-29 19:14:06 +01:00
Tahir Akhlaq
2c9ae60bbf corrected mob to use correct substate
- added global tick
- stubbed some more functions
- added checks for engaged/dead
- todo: everything else
2017-06-29 19:14:05 +01:00
Tahir Akhlaq
b9bfe5e985 cleaned up some of my retard with deltaTime and changed to DateTime for convenience swapping between seconds/milliseconds 2017-06-29 19:14:05 +01:00
Tahir Akhlaq
3bcaa4cc3e added some more ai stubs
- created mob class
- added pathfind and targetfind helper classes (todo: actually add stuff to them)
- added action queue helper class (todo: add shit to it)
2017-06-29 19:14:05 +01:00
Tahir Akhlaq
04890660c0 start of ai based on kjLotus's code on dsp 2017-06-29 19:14:04 +01:00
Tahir Akhlaq
c70cf022b7 moved vector3 to common
- changed distance checks to distance squared
- reexported central thanalan navmesh with cell size 0.60, height 0.26, radius 0.5, edge error 1.3, merged region size 30
- todo: main logic loop per zone and move this into proper ai classes
2017-06-29 19:14:03 +01:00
Tahir Akhlaq
872e56f8f9 navmeshes now super lightweight (<3 u devi)
- refactored some stuff
- unhardcoded navmesh loading
- included sharpnav license
2017-06-29 19:14:03 +01:00
Tahir Akhlaq
b640c87c69 fixed player position updates i think 2017-06-29 19:14:02 +01:00
Tahir Akhlaq
dd552ba69d adjusted roam radius slightly 2017-06-29 19:14:02 +01:00
Tahir Akhlaq
e09cb197b3 fixed finding random point retardation 2017-06-29 19:14:02 +01:00
Tahir Akhlaq
a62475e81e moved pathing crap out of actor
- despawn actors on moving too far from spawn
- added clampy stuff (<3 devi)
2017-06-29 19:14:01 +01:00
Tahir Akhlaq
bd97e72774 slightly smaller spawn leash
- removed try catch block
- todo: despawn actors on moving out of range
2017-06-29 18:45:43 +01:00
Tahir Akhlaq
4ad37f1011 fixed LookAt and IsFacing (<3 u devi) 2017-06-29 18:45:42 +01:00
Tahir Akhlaq
d72a2af641 initial navmesh stuff 2017-06-29 18:45:39 +01:00
Filip Maj
fc0c504c28 Merge branch 'packet_actortarget_rewrite' into guildleve 2017-06-29 11:39:02 -04:00
Filip Maj
f12ffc468d Updated lobby code for new Subpacket type. 2017-06-29 11:38:28 -04:00
Filip Maj
33e580ed38 Removed redundant queuepacket func. 2017-06-27 21:40:49 -04:00
Filip Maj
ab3e152b7d Fixed spawning being broken. 2017-06-27 21:30:32 -04:00
Filip Maj
3370309dd0 Cleaned up the code and fixed a bunch of bugs. Map server will no longer worry about base packets. 2017-06-27 21:08:30 -04:00
Filip Maj
4aa3a444d0 Messages for the Aetheryte Node appearing. 2017-06-27 20:17:24 -04:00
Filip Maj
08477780f8 Removed duplicate 0xD9 packet. Renamed 0xD8 to SetActorBGPropertiesPacket. 2017-06-27 17:37:13 -04:00
Filip Maj
516564a896 Refactored world server. 2017-06-27 17:31:17 -04:00
Filip Maj
9353f77db0 Removed duped battle packet. 2017-06-27 17:12:34 -04:00
Filip Maj
1339975ade Cleaned up inventory packets. 2017-06-27 17:07:29 -04:00
Filip Maj
7c4091a196 Finished refactoring Map Server. Clear of syntax errors. 2017-06-27 16:55:14 -04:00
Filip Maj
d8ac8216c4 More subpacket cleanup. 2017-06-27 13:52:47 -04:00
Filip Maj
a264745207 Started removing all target actor id references. 2017-06-27 13:23:05 -04:00
Filip Maj
c09471ed43 GL completion animation will only play to self now. 2017-06-26 00:14:26 -04:00
Filip Maj
00757b4ae7 Fixed dumb syntax error. 2017-06-25 23:43:02 -04:00
Filip Maj
fc96dac7c7 Fixed work values being totally wrong for guildleves. Added Add/Remove GL command. 2017-06-25 23:35:55 -04:00
Filip Maj
b5db036d71 Abandoning/Completing GLs now marks them correctly in the Journal. 2017-06-25 23:02:20 -04:00
Filip Maj
573b9a7202 Updated the GLWarpPoint actorClass to be clickable. 2017-06-25 22:44:48 -04:00
Filip Maj
e5afe8791b Implemented the ending portion of the guildleve. 2017-06-25 22:43:15 -04:00
Filip Maj
cd0bb10ef6 Forgot to push GL scripts. 2017-06-25 20:43:23 -04:00
Filip Maj
c071b9d684 Pushing new Aetheryte scripts that handle when GL is active. Finally added an error check for some lua callbacks. 2017-06-25 15:11:35 -04:00
Filip Maj
019e305525 Fixed redundant looping when removing/finishing a director. Fixed issue where packets to delete content group wouldn't send. Fixed issue where ContentGroups/Directors weren't clearing after deletion causing a growing amount of zombie groups/directors. 2017-06-25 14:52:32 -04:00
Filip Maj
875b76634a Implemented more of the Guildleve Director. Correct script is now autoloaded based on leveplate. Players are now added to the contentgroup on leve start. Moved animation and stuff to C# side of things. Cleaned up code. 2017-06-25 14:25:54 -04:00
Filip Maj
c42f1a08de Changed to Tutorial GL script as that is the correct one for our test GL. 2017-06-24 17:18:28 -04:00
Filip Maj
c78fa033af Fixed sbytes not processing correctly for work updates. Added a sync all function to guildleves. 2017-06-24 17:14:18 -04:00
Filip Maj
8fb4910320 Fixed work values not updating. GL UI now shows up though it isn't configured. 2017-06-24 16:58:02 -04:00
Filip Maj
186d5b5cc5 Had a bug where actor id was set to the wrong packet. Will have to also look at this target thing later. 2017-06-24 16:29:13 -04:00
Filip Maj
25cd75d40c Added way to instantiate a GL Director. Aetheryte parent now does it. 2017-06-24 15:57:46 -04:00
Filip Maj
8ccd3439c1 Added marker update method for guildleves. 2017-06-24 15:54:02 -04:00
Filip Maj
bfaa25cb39 Forgot the aetheryte script. 2017-06-24 15:51:06 -04:00
Filip Maj
c7acef20a9 Added missing gl scripts. 2017-06-24 15:50:03 -04:00
Filip Maj
a80c80454b Added more work values and guildleve funcs. Also realized target will always == the queuedpacket session. This will make broadcasting packets easier once cleaned up. 2017-06-24 15:47:53 -04:00
Filip Maj
eb17da1c89 Modified how directors work to allow for persistence. Implemented GuildleveDirector object and it's work values. 2017-06-24 15:31:42 -04:00
Filip Maj
2d7d10a417 Renamed Item dataobject to ItemData. Added guildleve data. 2017-06-24 14:12:52 -04:00
Filip Maj
44a76c94af Added guildleve helper funcs. 2017-06-24 12:07:27 -04:00
Filip Maj
f00e878dd0 Fixed session issue. Still a stopgap until d/cing is implemented. 2017-06-19 23:11:24 -04:00
Filip Maj
0c8642d6ab Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2017-06-19 22:24:45 -04:00
Filip Maj
793f5323fb DB update for inn door fixes. Also YoshiP added. 2017-06-19 22:24:31 -04:00
Filip Maj
7f6b291366 Added script for ItemStorage npc. Added scripts for both types of inn exit doors. Added BountyPresenter script (YoshiP). 2017-06-19 22:23:27 -04:00
Filip Maj
c1d67538f3 Added item storage packet for armoire. 2017-06-19 22:21:21 -04:00
Filip Maj
dbaea65c19 Fixed how login/zoning session start is handled. Should fix the bug where a player could not relogin into a server twice. 2017-06-19 16:30:04 -04:00
Filip Maj
ed5ee01ba6 Firedance description was being referenced wrong. 2017-06-15 01:21:16 -04:00
Filip Maj
b838027cba Partially figured out the SetSpecialEventWork Packet. 2017-06-15 01:18:57 -04:00
Filip Maj
1d9f57a385 Cleaned up the emotes code. 2017-06-15 00:19:18 -04:00
Filip Maj
0e8de966a9 Fixed emotes, they all work now. 2017-06-15 00:05:14 -04:00
Filip Maj
cdfa2f682e Fixed the broken elevator in Ul'dah. Finished the one in Limsa. 2017-06-14 22:41:39 -04:00
Filip Maj
866e2d3559 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2017-06-14 22:24:26 -04:00
Filip Maj
d96d5b29a5 Fixed issue where spawn packets were sent on zone out. Added all npcs to Camp Bearded Rock. Rewrote how mapobjs get loaded in, no more hardcodes. Added tons mapobjs to the DB. Added ferry npcs. 2017-06-14 22:24:09 -04:00
CuriousJorge
fdf30b4615 Merged in CuriousJorge/ffxiv-classic-server/develop (pull request #45)
Applying bugfix from Master to Develop.
2017-06-15 01:59:00 +00:00
CuriousJorge
cfb3a473c1 Applying bugfix from Master to Develop.
Fixes the issue where actors are spawning in with default movement speed instead of their current.
2017-06-06 17:33:02 -04:00
Joseph Mikel Keller
5c350e4ffa Merged in dude22072/ffxiv-classic-server-1/dude22072/databasephp-edited-online-with-bitbucket-1492196780169 (pull request #42)
Tells user incorrect username/password instead of "VerifyUser failed."
2017-06-06 16:43:13 +00:00
Tahir Akhlaq
4e8ce558a7 Merged in takhlaq/ffxiv-classic-server/develop (pull request #44)
fixed some races
2017-06-06 16:42:14 +00:00
Tahir Akhlaq
72099e92bb fixed some races 2017-06-06 02:11:45 +01:00
Filip Maj
52cacb1ded Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop
# Conflicts:
#	FFXIVClassic Map Server/packets/send/Actor/SetActorSubStatPacket.cs
2017-05-16 23:44:42 -04:00
Filip Maj
c67c5f3bdf Bug fix on broadcast packet method, filled out what 0x144 does. 2017-05-16 23:43:53 -04:00
Filip Maj
5d65965ec0 Bug fix on broadcast packet method, filled out what 0x144 does. 2017-05-16 23:43:07 -04:00
Filip Maj
08b3564d7e Added things for testing mapobjs. 2017-05-05 02:37:01 -04:00
Filip Maj
9505cd71be Repositioned LaNoscea and Shroud Aetherytes. Linked them up too. Teleporting to one now causes you to appear *near* it, and facing it. 2017-05-02 21:44:44 -04:00
Filip Maj
844f21d9a4 Finished off the teleport script. Still requires all the aetheryte positions filled out. 2017-05-01 22:55:47 -04:00
Filip Maj
1516e0bc50 Added homepoint and aetheryte code. You can set the homepoint on an aetheryte or inn and the return menu will show the correct response. Added effects/msgs to teleport/return. Some sql changes I forgot. 2017-05-01 22:30:43 -04:00
Filip Maj
8c9ecebae6 Added a "silent" option for LuaEngine calls. More content instance work. Full classpath now used for zones. 2017-04-29 20:30:54 -04:00
Filip Maj
cc44d6b63c Forgot to push the sql changes for linkshells and retainers. 2017-04-15 16:41:01 -04:00
Filip Maj
9c2cdf9b5d Forgot to add script for quest abandon. 2017-04-15 16:37:14 -04:00
Filip Maj
9a2a79095c Added a spawn command for testing. Added scripts for the mole and lemming enemies. A content group is formed when you start the limsa opening (still testing). Added Vkorolon's dialog for the gridania opening echo. 2017-04-15 16:36:39 -04:00
Filip Maj
2de4934c41 Fixed battle npcs appearing strangely (no nameplate, wrong colour, etc), and implemented content groups! 2017-04-15 16:33:56 -04:00
Joseph Mikel Keller
9513389e0a database.php edited online with Bitbucket 2017-04-14 19:08:08 +00:00
Joseph Mikel Keller
b490cdf124 database.php edited online with Bitbucket 2017-04-14 19:06:25 +00:00
Filip Maj
c6307dde35 Forgot a nil in the "send game message" params, otherwise wrong overload is run. 2017-04-09 14:07:34 -04:00
Filip Maj
8c07e3f549 Added the changed schema for npc linkshells in the db. 2017-04-09 14:04:23 -04:00
Filip Maj
0d4ed1d1c8 Cleaned up the way a npc ls is set. Added an optimization, no changes are made if it is being set to the same value already set. Added the handler for npc linkshells when they are used. 2017-04-09 14:01:15 -04:00
Filip Maj
90e48f9ddd Added npc ls saving/functionality. 2017-04-09 12:48:27 -04:00
CuriousJorge
3d4bf3465b Merged in CuriousJorge/ffxiv-classic-server/develop (pull request #41)
"Seeing the Seers" quest etc3g0 scripted + minor fixes
2017-04-09 15:32:54 +00:00
CuriousJorge
3145ec5663 "Seeing the Seers" quest etc3g0 scripted, no reward handling currently. Requires actor "Nellaure" (http://ffxiv.gamerescape.com/w/index.php?title=Nellaure) to be added in. Hangs out in back-right corner of Carpenter's Guild.
Added a quest completion check to etc5g0.lua to prevent it showing "!" on quest-givers' head when you've cleared the quest already.
Fixed regression on select GM commands, !warp instant-warps within same zone again, !mypos reports to the thousandths place, !speed command works with one argument again.
2017-04-05 18:39:04 -04:00
Filip Maj
4bb222a47a Current phase wasn't being loaded in. Fixed. 2017-04-04 01:42:34 -04:00
Filip Maj
3269621dec Fixed Vkorolon not showing completion icon on login if in phase 1. 2017-04-04 01:37:27 -04:00
Filip Maj
c71aa0b45e Fixed crash if completionCheck callback wasn't there. 2017-04-04 01:25:08 -04:00
Filip Maj
e38a995574 Fixed a game message not appearing when objectives were completed. 2017-04-04 01:21:06 -04:00
Filip Maj
96c0f3444e Fixed the journal command. Wasn't sending correct phase. 2017-04-04 01:11:18 -04:00
Filip Maj
7fa4a1eb80 Added callbacks to help with quest management. Abandoning a quest now works. 2017-04-04 01:10:26 -04:00
Filip Maj
9d63be52e3 Added the Waste Not Want Not quest. 2017-04-02 23:50:51 -04:00
Filip Maj
c0f7f1b1ad Fixed quest commands not working from Lua. The uint/string overload was confusing it. 2017-04-02 18:44:47 -04:00
Filip Maj
a866688344 Added working import script for Windows (batch). 2017-04-02 18:29:07 -04:00
Rober Baker
0546b81cff Merged in reiichi001/ffxiv-classic-server/develop (pull request #40)
Typo fixes
2017-04-02 19:59:18 +00:00
Rober Baker
358afbace3 Merged in reiichi001/ffxiv-classic-server (pull request #39)
Small adjustments for new users
2017-04-02 19:58:32 +00:00
Robert Baker
be5a517aaa Typo fixes 2017-04-02 12:56:05 -07:00
Filip Maj
91820dc933 Forgot linkshell sql file. 2017-04-02 15:13:24 -04:00
Robert Baker
6642ed7e12 Fixed postbuild typos.
Automatically copy the scripts folder.
Pre-edited player.lua to disable addQuest / Directors.
2017-04-02 11:34:14 -07:00
Filip Maj
248ea0cce1 Merge branch 'develop' into lua_waiters 2017-04-02 14:29:37 -04:00
Filip Maj
be4b3b506f Pushing sql changes. 2017-04-02 14:29:04 -04:00
Filip Maj
43e1fbfab3 Pushing scripts. Also modified how private areas work. The type value is now appended to the name. 2017-04-02 14:26:36 -04:00
Filip Maj
2b780687dd Actor state from a spawn location wasn't being set. 2017-04-02 13:48:56 -04:00
Filip Maj
e0c9ca2bc2 Added break in the "setPushCircle" function. Fixed bug in the actor properties util. If a packet got full while inserting the property, it wouldn't get inserted in the next one. 2017-04-02 12:51:23 -04:00
Filip Maj
6c366110ef Added "CanAcceptQuest" and "IsQuestCompleted" helpers. 2017-03-28 18:03:16 -04:00
Tahir Akhlaq
6dd8bdda0c Merged in takhlaq/ffxiv-classic-server/null (pull request #38)
added db launch args and improved import time on gamedata_actor_class.sql
2017-03-27 16:57:02 +00:00
Tahir Akhlaq
a2a30003e0 added db launch args and improved import time on gamedata_actor_class.sql 2017-03-25 04:36:19 +00:00
Filip Maj
b345521f79 callClientFunction now returns ALL results. Fixed some scripts, finished fixing up Gridania opening script. 2017-03-21 00:43:30 -04:00
Filip Maj
6e12668176 Fixed the journal entry not clearing on removal. 2017-03-20 23:37:05 -04:00
Filip Maj
8f89eb8f23 Added quest accept/complete functions, and fixed a bug with removing quests from the DB. 2017-03-20 23:31:11 -04:00
Filip Maj
a77d2a9b48 Fixed crash. 2017-03-20 21:53:43 -04:00
Filip Maj
0a94840419 Checks and fixes for lua. 2017-03-20 21:51:43 -04:00
Filip Maj
7c25b14640 Changed "SendRequestedInfo" to "SendDataPacket" as that's the actual name of the packet. Copied all the progress with the Limsa Opening director to Gridania and Uldah. 2017-03-19 12:35:21 -04:00
Filip Maj
1bf25b2a2b Fixed a bunch of bugged scripts and cleaned up the quest flags. 2017-03-19 12:17:09 -04:00
Filip Maj
4f339709d5 Added scripts for NPCs in the Limsa echo instance and Gridania opening post-battle instance. 2017-03-19 11:41:29 -04:00
Filip Maj
7b205c7b9b Fixed syntax error in tutorial script. Finished fleshing out the opening script and related scripts for Limsa. 2017-03-19 11:40:41 -04:00
Filip Maj
77e0639410 Realized the start event packet after a zoneIn kickevent is weird and malformed, fixed for that usecase. Fixed bug with getting PrivateArea script. Missing area scripts now don't show a message (they were optional). Finished scripting out Limsa opening battle. 2017-03-19 11:39:21 -04:00
Filip Maj
545ce18f1f Merge branch 'lua_waiters' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into lua_waiters 2017-03-17 17:20:34 -04:00
Filip Maj
43c0925dee Added tutorial helper script. 2017-03-17 17:20:03 -04:00
Filip Maj
ce13827bce Fixed args being all wrong. 2017-03-14 23:13:54 -04:00
Filip Maj
b81141a158 More fixings and improvements. 2017-03-14 18:33:33 -04:00
Filip Maj
718bc28c57 Implemented "wait" functionality to the lua engine. Lost commits due to screw up. 2017-03-13 14:06:57 -04:00
Filip Maj
bc30958d37 New sql entries for limsa echo instance. Fixed PrivateAreaPastExit class entry. 2017-03-08 09:13:10 -05:00
Filip Maj
0c3f6cc9c4 Fixed bug with old "findActor" code since private areas were added. Add scripts for npcs in echo during limsa opening. 2017-03-08 09:12:14 -05:00
Filip Maj
eb324062da Phasese are now saved. 2017-03-07 21:44:57 -05:00
Filip Maj
de8877c1a4 Scripts were all broken. Fixed. 2017-03-07 17:27:33 -05:00
Joseph Mikel Keller
dc0b886691 Merged in dude22072/ffxiv-classic-server-2/dude22072/added-server_seamless_zonechange_boundcs-1483400391812 (pull request #34)
server_seamless_zonechange_bound.sql update
2017-03-07 17:55:33 +00:00
Rober Baker
8871f47066 Merged in reiichi001/ffxiv-classic-server/develop (pull request #37)
Small typo fixes
2017-03-07 17:53:37 +00:00
Franz Renatus
23ce361801 Fixed Map Server build script to copy scripts folder.
Added world_config.ini to World Server build script.

Adjusted characters.sql to make the lobby server happy again.
2017-03-07 09:16:55 -08:00
Filip Maj
d918ad3776 New scripts for the opening private areas, as well as db updates. 2017-03-07 08:32:57 -05:00
Filip Maj
e898c045f7 Overhaul of the director system and opening quests. Private Areas further implemented as well. 2017-03-07 00:09:37 -05:00
Filip Maj
dcaad5729d Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2017-01-29 11:08:24 -05:00
Filip Maj
f7482781e5 Rewrote directors so that they can work in the new system. Began adding content groups to the map server. 2017-01-29 11:07:28 -05:00
Filip Maj
40deaf3075 Fixed accidental hardcode. 2017-01-27 10:04:24 -05:00
Filip Maj
663c591a89 Merge branch 'launcher_editor' into develop 2017-01-26 19:42:07 -05:00
Filip Maj
031dae2c84 Added inputs, launcher editor more or less works. 2017-01-26 19:41:10 -05:00
Filip Maj
ab3ca412b3 Finished writing most of this exe patcher. 2017-01-26 19:07:47 -05:00
Filip Maj
ad88c0b28a Added a work value change function for testing. 2017-01-24 09:06:28 -05:00
Filip Maj
9372b4bc32 Added a thread and update() calls for gamestate changing. 2017-01-16 19:14:13 -05:00
Filip Maj
6a6ee67ae2 Conjurer door id. 2017-01-11 22:03:30 -05:00
Filip Maj
e6af0ef842 Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2017-01-11 22:02:00 -05:00
Filip Maj
b5a48b0eff Added more MapObjects. 2017-01-11 22:01:36 -05:00
Filip Maj
a8f3fe28d4 Uploaded the 1.0 launcher website as well as test patcher website. 2017-01-11 19:21:33 -05:00
Filip Maj
63b3098592 Lot of scrapped classes added. 2017-01-11 01:32:33 -05:00
Filip Maj
8b4eb8c57e Added retainer push command and fixed a bug with kickEvent (kinda???) 2017-01-10 23:59:25 -05:00
Filip Maj
b9c0084080 Fixed pushCommand load bug. Set all Aetherytes to wrong command id; fixed. 2017-01-10 23:47:37 -05:00
Filip Maj
c961ccd5bf Added all aetherytes classes and some other fixes. 2017-01-10 23:19:59 -05:00
Filip Maj
4a544a9ea3 The required sql file. 2017-01-10 16:45:38 -05:00
Filip Maj
fb1d22d731 Push command loading implemented. 2017-01-10 16:43:03 -05:00
Filip Maj
9bc3fc8dd7 Setting the active linkshell now works. 2017-01-09 23:12:56 -05:00
Filip Maj
fe1a652cd1 Removed build script to get this thing to compile. 2017-01-09 00:30:12 -05:00
Filip Maj
79de4fd1ff Merge branch 'develop' into group_work
# Conflicts:
#	FFXIVClassic Map Server/ConfigConstants.cs
2017-01-09 00:19:39 -05:00
Filip Maj
bc72147622 Added scripts needed. 2017-01-09 00:17:46 -05:00
Filip Maj
771b5b6d81 LS kicking and leaving work. 2017-01-09 00:12:11 -05:00
Filip Maj
61e4effd74 Started implementing LS management. Rank change works. 2017-01-08 23:13:15 -05:00
Filip Maj
68772a2011 Merge branch 'group_work' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into group_work 2017-01-08 21:43:04 -05:00
Filip Maj
108d8be013 Linkshell inviting completed. 2017-01-08 21:42:43 -05:00
Filip Maj
8499eeff39 Started work on the launcher/patcher editor. 2017-01-04 17:30:36 -05:00
Filip Maj
4b0ffb3882 Fixed the last actor speed. It was active mode speed. 2017-01-03 19:02:35 -05:00
dude22072
5b5bbc23b4 Added server_seamless_zonechange_bound.csv that was posted by
Jorge(@Tiam#8657) in Discord to server_seamless_zonechange_bounds.sql
2017-01-02 23:40:17 +00:00
Filip Maj
8a0ebe7ec4 Required scripts to make it work. 2017-01-02 14:38:56 -05:00
Filip Maj
5d494255ad Party invite done, as well as chat. Fixed double output of say packets. Note: Still need to implement name version of invite!!! 2017-01-02 14:35:11 -05:00
Filip Maj
5af1f6dba6 Relation group work. 2017-01-02 11:47:14 -05:00
Filip Maj
6ba1f968c3 Party leave/disband done. 2016-12-22 14:47:24 -05:00
Filip Maj
7c29a850c4 Scripts for party commands. 2016-12-21 21:50:45 -05:00
Filip Maj
2b10221a75 Party sync is done. Finished kick/promote code. Client is now always at the top of pt list. 2016-12-21 21:49:50 -05:00
Filip Maj
506bcbaf87 Added missing opcodes. 2016-12-21 20:04:33 -05:00
Filip Maj
16c9b741bf Kicked/Promote leader added but broke login. D/Cing now. 2016-12-21 18:02:50 -05:00
Filip Maj
e89b7557b3 Zone server now uses the World server's group classes. MotD now shows proper world name. Added party functions to zone server. 2016-12-21 09:27:51 -05:00
Filip Maj
ae38ee1bc1 Merge branch 'group_work' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into group_work
# Conflicts:
#	FFXIVClassic Map Server/WorldManager.cs
2016-12-21 08:28:24 -05:00
Filip Maj
bf9095822e Got party leader working. Added linkshell world/zone requests. 2016-12-21 08:27:23 -05:00
Filip Maj
2bdc238bc2 Added party sync packet which will sync member info between world/zone servers. 2016-12-20 19:17:50 -05:00
Filip Maj
a68866617f Removed a copy/paste error in the CreateLinkshell db code. 2016-12-18 10:13:04 -05:00
Filip Maj
4109f33b6e Relation code finished. 2016-12-18 10:07:06 -05:00
Filip Maj
7036ef363d Implemented MotD. Groups are now sent from world server to client, and also initialized. Retainers finished and are also sent. 2016-12-18 09:50:23 -05:00
Filip Maj
31446f37fa More cleanup (moved groups to WorldMaster class) and fixed the project file. 2016-12-17 09:37:18 -05:00
Filip Maj
2cc63960a7 Linkshell and WorkValue work. 2016-12-16 20:06:17 -05:00
Filip Maj
1148619ca5 More group work. Added packet operations to the world server so it can send global group info. 2016-12-15 12:19:44 -05:00
Filip Maj
6c409e93a9 Random work. 2016-12-13 15:02:28 -05:00
Filip Maj
fd2df829de Forgot stuff. 2016-12-12 19:05:06 -05:00
Filip Maj
31b13300ac Added all the base code for managing world-scope groups. 2016-12-12 19:03:25 -05:00
Filip Maj
09e1e31e79 Added packet 0xda 2016-12-12 10:11:27 -05:00
Filip Maj
b2c1c2895d Added new packets for controlling BG objects. Added group delete packet. Fixed crash if tried to warp to non-existent zone. Added a create LS db method. 2016-12-11 23:31:13 -05:00
Filip Maj
feb73a8444 Added subclassed groups to auto-set workvalues. 2016-12-06 08:26:16 -05:00
Filip Maj
f4e238f4be Merged in takhlaq/ffxiv-classic-server/ezpz (pull request #32)
added launch args for ip/port and default config loading
2016-12-05 15:29:50 +00:00
Tahir Akhlaq
ca44400048 cleaned up some spacing 2016-12-05 14:36:40 +00:00
Tahir Akhlaq
a2d4879cdd Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into ezpz
# Conflicts:
#	sql/characters.sql
2016-12-05 14:29:19 +00:00
Tahir Akhlaq
4a320d7096 added launch args for ip/port and default config loading
- fixed char create issues by adding default values to fields (todo: fix actual query)
- added post build command to copy scripts folder to bin
2016-12-05 14:26:20 +00:00
Filip Maj
96a29a9f04 Merged in dude22072/ffxiv-classic-server-1/dude22072/characterssql-auto_increment-1480820519818 (pull request #30)
AUTO_INCREMENT
2016-12-05 13:46:18 +00:00
Filip Maj
25e55bf6df Merged in takhlaq/ffxiv-classic-server/linux (pull request #29)
fixed linux build and import script
2016-12-05 13:46:02 +00:00
Filip Maj
c2a3641d08 Extended "Group" and created all the subgroups to cleanup code as well as make setting "work" values easier. 2016-12-04 11:59:54 -05:00
Filip Maj
f286922974 Deleted the list folder and anything in it. This was the old way before I realized how groups work. 2016-12-04 10:52:22 -05:00
Filip Maj
0317bea83b Redid the group sending using the new methods. 2016-12-04 10:51:27 -05:00
Filip Maj
18e9ee5f63 Forgot the "SynchGroupWorkValuesPacket" and some merging stuff. 2016-12-04 10:18:04 -05:00
Filip Maj
52703537e9 Forgot the "GroupCreatedPacket". 2016-12-04 10:12:33 -05:00
Filip Maj
df6e16103c Manually added the group packets and dataobjects into dev branch because the working_on_groups branch is so old it probably will break stuff. 2016-12-04 09:52:57 -05:00
dude22072
7e535a9398 users.sql AUTO_INCREMENT 2016-12-04 03:06:04 +00:00
dude22072
c04680ea38 characters.sql AUTO_INCREMENT 2016-12-04 03:02:15 +00:00
Filip Maj
101070954d Localhost Character's id was hardcoded by accident. 2016-12-03 18:56:32 -05:00
Filip Maj
b1998d5f73 Pushing sql updates. 2016-12-03 17:40:45 -05:00
Filip Maj
3864bf6d85 Merge branch 'proxy_server' into develop
# Conflicts:
#	FFXIVClassic Common Class Lib/packages.config
2016-12-03 14:03:13 -05:00
Filip Maj
4ce4647a75 If a player tries to zone to a offline server they will see a standard error message. Also a reconnection attempt will be made on a disconnected server. 2016-12-03 14:00:24 -05:00
Filip Maj
260878df38 Fixed login breaking due to destinationZone not going to 0 after switch or crash. 2016-12-03 13:33:39 -05:00
Filip Maj
ebd8ab0580 Fixed random crashes when zoning. Was due to improper write of the SessionEndPacket. For extra safety db is locked until zone in happens. Added some logs. Seems to be all working! 2016-12-03 13:23:32 -05:00
Filip Maj
e30831fdc5 Built subpackets to let the zone servers talk to the world server. Implemented cross-server zoning but the E2 packet or something isn't being sent. 2016-12-03 12:19:59 -05:00
Filip Maj
315f2e579c Merged in dude22072/ffxiv-classic-server/dude22072/marketentrancelua-syntax-error-1475561003225 (pull request #26)
MarketEntrance.lua syntax error
2016-10-05 16:18:12 -04:00
dude22072
6e7459a2f8 MarketEntrance.lua syntax error 2016-10-04 06:03:33 +00:00
Filip Maj
58fda93b45 Began working on server zone changes. 2016-09-26 16:20:01 -04:00
Filip Maj
5370f13b2b Fixed login not working, was due to packets that got queued not flushing. !!!Need to find solution!!! Added a optimization: Actors with 0 battle args are now concidered "static" and will not send their position updates. Removed some debug print statements. 2016-09-24 14:17:31 -04:00
Filip Maj
d931f71b06 Map server will only load maps it's set to load. 2016-08-29 13:39:50 -04:00
Filip Maj
62daa4db89 Removed duplicate CommandProcessor. It is held by the Server object now. GetSession by name now ignores case. 2016-08-29 12:48:23 -04:00
Filip Maj
e106eafb6c Server.cs Cleanup2 2016-08-29 12:41:33 -04:00
Filip Maj
c9feef07b7 Moved ZoneConnection to dataobjects namespace. Cleaned up Server.cs. 2016-08-29 12:40:47 -04:00
Filip Maj
cf38454c8f Cleaned up a lot of the "ConnectedPlayer" objects, turning them into "Session" objects. A lot of duplicate lists were also removed. 2016-08-29 12:37:41 -04:00
Filip Maj
06e7ea59f4 Fixed NLog config for map server. Added some debug printouts while testing. 2016-08-29 09:03:48 -04:00
Filip Maj
37b098e87a Added a sleep during debug so zone server launches after map server ready. 2016-08-29 08:54:37 -04:00
Filip Maj
6bffe69b21 More work on the world server. Modified map server to communicate with it. 2016-08-29 08:17:14 -04:00
Filip Maj
bd26a71fef Changed folder from Proxy to World. Did some nlog configing. 2016-08-28 14:25:37 -04:00
Filip Maj
0f093235f8 Default speeds were not being set, and on actor load *currentSpeed* wasn't being loaded. 2016-08-28 08:06:10 -04:00
Tahir Akhlaq
92be59d020 fixed linux build and import script 2016-08-27 03:50:02 +01:00
Filip Maj
364ab40b3f Added decompression/compression of packets. Cleaned up handshaking. 2016-08-24 15:41:54 -04:00
Filip Maj
4aae16e458 More session handling code added. 2016-08-24 14:18:37 -04:00
Filip Maj
a1ca960543 More work on the world server. 2016-08-23 16:57:24 -04:00
Filip Maj
e24a6f99cb Some more work on the world server. 2016-08-22 14:18:37 -04:00
Filip Maj
c67f74130f Moved packet structures to common. 2016-08-22 10:43:04 -04:00
Filip Maj
62cc343f51 Player chocobo issuance is now removed, and you are given a chocobo whistle if you didn't have one. 2016-08-21 20:11:50 -04:00
Filip Maj
8725377168 Changed InfoRequestResponsePacket to GenericDataPacket as that is the proper use/term. Added the city exit spawn locations. Did more work on the chocobolender script. Most of the issuing portion is done. Also can now summon through the lender. 2016-08-21 19:51:49 -04:00
Filip Maj
d5f17c01a8 Added changes to the chocobolender script and global script. Working off of "thetestgames" code. 2016-08-21 18:21:00 -04:00
Filip Maj
d6277bc722 Sql update for the last commit. 2016-08-21 18:18:11 -04:00
Filip Maj
316e326d71 GM tickets can now be in an open/closed state. Added some helper functions for currancy, and added functions to allow changing chocobo appearance. 2016-08-21 18:16:54 -04:00
Filip Maj
685fe7dd5a Fixed and improved a bunch of the recently commit Support Desk tables and database accessors. Removed a file that doesn't exist added from last commit. 2016-08-20 19:16:33 -04:00
Filip Maj
c087fb44c0 Merged in nxtstudios/ffxiv1.0-server (pull request #24)
Added DB support for Support Desk packets and fixed paths to work on Linux/OSX
2016-08-20 13:29:12 -04:00
Jordan Maxwell
00e5e4f642 Updated Chocobo Lender script 2016-08-19 17:43:04 -05:00
Jordan Maxwell
46350a0724 Fixed Bugs 2016-08-19 16:32:14 -05:00
Jordan Maxwell
fb18c1fbe4 Added DB Support for Chocobo Lenders 2016-08-19 14:40:43 -05:00
Jordan Maxwell
4f3828e594 Added MySQL tables for Support Desk 2016-08-19 00:10:07 -05:00
Jordan Maxwell
270d4ce436 Fixed MySQL Syntax issues 2016-08-18 23:36:04 -05:00
Jordan Maxwell
7c9077beec Added support for Linux/OSX Paths 2016-08-18 22:59:23 -05:00
Jordan Maxwell
d7166cadc0 Added GM Ticket support on the DB 2016-08-18 22:58:09 -05:00
Filip Maj
38014f8a16 Merged in CuriousJorge/ffxiv-classic-server/script_fixing (pull request #23)
Limsa/Gridania NPC fixed scripts.
2016-08-18 16:47:14 -04:00
CuriousJorge
4f48643c5c Limsa/Gridania NPC fixed scripts. Scripts still needed for Aubrenard & Gridania Aetheryte.
Some required changes to the database:

Task Board - Change 1200195 in gamedata_actor_class to /Chara/Npc/Object/TaskBoard
Serpent_Private_White - Change 1500324 in gamedata_actor_class to /Chara/Npc/Populace/PopulaceCompanyWarp
Beaudonet - Adjust 1001708 in gamedata_actor_class.  There is a linebreak in there causing problems
2016-08-17 23:27:31 -04:00
Filip Maj
3490f366a2 Merged in CuriousJorge/ffxiv-classic-server (pull request #21)
Updated GM Commands.
2016-08-14 10:52:52 -04:00
Filip Maj
13362d347c Merged in xdemolish/ffxiv-classic-server/develop (pull request #22)
improved import times on a few tables
2016-08-14 10:51:39 -04:00
Tahir Akhlaq
8665c1a226 improved import times on a few tables 2016-08-14 15:49:32 +01:00
Filip Maj
b6c3c7f71c Added MS Compilers package to let solution compile in VS2013. Added new sql files with Gridania NPCs. Added the new seamless boundry table. 2016-08-14 09:45:06 -04:00
Filip Maj
63ac56224e Merge branch 'develop' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into develop 2016-08-14 08:52:27 -04:00
Drajiel
09705bec4e Updated Commands. 2016-08-11 20:02:01 -04:00
Filip Maj
d5f0cbef8c Merge branch 'master' into develop 2016-08-09 14:22:27 -04:00
Filip Maj
595a53ed9e Forgot to push file for seamless zone change. 2016-08-05 18:25:24 -04:00
Filip Maj
b3920f9630 Music is faded in on seamless change instead of instant. 2016-08-05 18:25:08 -04:00
Filip Maj
c4c43421f3 Forgot ObjectItemStorage script. 2016-08-05 18:24:17 -04:00
Filip Maj
5e926bf668 Added Gridania scripts and various others. Fixed error messages popping for scripts that may not use certain functions. 2016-08-05 18:23:59 -04:00
Filip Maj
0c435d91c9 Merged in xdemolish/ffxiv-classic-server/gg (pull request #20)
readded functions to utils (note to self: read both files before merging)
2016-08-03 17:30:06 -04:00
Tahir Akhlaq
2233f48719 note to self: read both files before merging 2016-08-03 16:54:23 +01:00
Filip Maj
67928ee875 Seamless zoning implemented WOOOO! 2016-07-31 23:00:38 -04:00
Filip Maj
8eb257aba4 Seamless boundries added to DB and loaded by WorldManger. 2016-07-31 22:30:54 -04:00
Filip Maj
b43a6885c5 Added functions to allow for an improved seamless zone change. Player can now pull actors from two zones when performing a seamless zone change to give a improved feel. 2016-07-31 21:48:17 -04:00
Filip Maj
63edbe81f3 Added code to generate lua files from db. 2016-07-31 21:07:37 -04:00
Filip Maj
205136d661 Improved trigger box packet. 2016-07-31 21:07:26 -04:00
Filip Maj
a4d3e91085 Merged in xdemolish/ffxiv-classic-server/misc2 (pull request #18)
fixed import script, improved db import times, fixed logging and warp command (should be 5000% legit now)
2016-07-27 12:57:13 -04:00
Tahir Akhlaq
065fe05795 fixed import script, improved db import times, fixed logging and warp command (should be 5000% legit now)
- improved import times for gamedata tables (there's prolly other innodb tables too, i didnt check though)
- fixed issue where player wouldnt be readded to zone on warping if destination wasnt valid
- corrected typo in warp command lua description
- added logger for lua cause i forgot to last time
2016-07-27 17:23:52 +01:00
Filip Maj
2939683183 Added property flags for actors. Cleaned up NPC constructor. 2016-07-24 10:21:45 -04:00
Filip Maj
4ef62a16ec Merge branch 'master' into develop 2016-07-17 13:06:56 -04:00
Filip Maj
7f65cfcbbf Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server 2016-07-17 13:06:38 -04:00
Filip Maj
70b4fc8630 Removed some packet debug outputs. 2016-07-17 09:21:17 -04:00
Filip Maj
2c30b7dfc1 Merged in xdemolish/ffxiv-classic-server/lua_commands (pull request #17)
derped with some debug logging (thought i pushed this earlier)
2016-07-17 09:20:13 -04:00
Tahir Akhlaq
59f3cfa2f1 derped with some debug logging (thought i pushed this earlier) 2016-07-17 11:34:37 +01:00
Filip Maj
136ced3aae Added all the shop keeper scripts in Ul'dah. Fixed some broken populace scripts. Changed .ini files, wrong default. Fixed a syntax error in CommandProcessor.cs. 2016-07-16 20:12:04 -04:00
Filip Maj
5b7ad2364b Merge branch 'master' into develop 2016-07-16 20:04:49 -04:00
Filip Maj
302d7bd68a Merged in xdemolish/ffxiv-classic-server/lua_commands (pull request #16)
dynamic gm commands + packet logging fix
2016-07-16 19:52:54 -04:00
Filip Maj
d26b64b458 Fixed some minor lua related crashing when the parent file was not found for some reason. Used decorated message for error output, not normal message. 2016-07-16 19:52:13 -04:00
Tahir Akhlaq
8839e75557 missed some left over files 2016-06-24 22:14:17 +01:00
Tahir Akhlaq
5fc0e0eeca Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into lua_commands
# Conflicts:
#	FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
#	FFXIVClassic Map Server/lua/LuaEngine.cs
#	data/scripts/global.lua
2016-06-24 22:13:17 +01:00
Tahir Akhlaq
30b0d4a97d implemented sendpacket and speed commands
- fixed data race on logging in
- todo: implement reloadzones, reloaditems, property, property2
2016-06-24 20:52:30 +01:00
Filip Maj
110cfbccc2 Fixed errors in the spawn location tables. 2016-06-21 23:00:39 -04:00
Filip Maj
3cd181f5da Ported over the Limsa/Uldah opening zone scripts. Still not 100% done. 2016-06-21 22:50:30 -04:00
deviltti
7a25c818f2 demo...srs? 2016-06-21 21:52:40 -04:00
Tahir Akhlaq
bb02f94d38 changed date formatting for logging 2016-06-22 02:31:05 +01:00
deviltti
b8a563f9d7 Lobby and game server packet ConsoleColor to NLog cleanup. 2016-06-21 21:13:01 -04:00
Filip Maj
926e9146e2 Fixed a few scripts. Jellyfish init script was built so it didn't crash boat zone. 2016-06-21 20:07:02 -04:00
Filip Maj
4c7316702d Limsa Town npcs ported over. 2016-06-21 19:54:52 -04:00
deviltti
0c197f34a1 Okay now. 2016-06-21 18:58:33 -04:00
deviltti
590ad3e002 Reimplemented ConsoleColor for packets in NLog. 2016-06-21 18:52:20 -04:00
Filip Maj
44acee7e6d Made a note that Guencen is unreachable and has no real script. 2016-06-21 18:01:12 -04:00
Filip Maj
d06bf5499f Set Ansgor to correct talk. 2016-06-21 17:56:38 -04:00
Filip Maj
3969fff64a Finished converting over all scripts. 2016-06-21 17:48:50 -04:00
Tahir Akhlaq
0aac675b30 cleaned up previous commit 2016-06-21 21:47:07 +01:00
Filip Maj
8b44d90114 Modified all wil0Town01 scripts to new way. 2016-06-21 15:48:16 -04:00
Filip Maj
ff2f587959 Modified all wil0Town01a scripts to new way. 2016-06-21 15:29:48 -04:00
Filip Maj
1242a8b00c New event conditions to take advantage of PlaceDrivenCommands. 2016-06-19 23:24:19 -04:00
Filip Maj
1546ed54fc Moved aetheryte script to new system. 2016-06-19 23:23:01 -04:00
Filip Maj
97c1fb06cf More script work. 2016-06-19 23:16:31 -04:00
Filip Maj
8743042950 Cleaned up the new scripting code. Added a helper function to do the yielding automatically. Modified all the scripts to use the new system and added a few new ones. 2016-06-19 18:52:34 -04:00
Filip Maj
51bbf4ae2e Non-npc stuff is now also using script system. Wrote new scripts for all sidemenu commands. 2016-06-18 12:26:29 -04:00
Tahir Akhlaq
37d91480f9 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into lua_commands
# Conflicts:
#	FFXIVClassic Common Class Lib/packages.config
#	FFXIVClassic Lobby Server/Program.cs
#	FFXIVClassic Map Server/CommandProcessor.cs
#	FFXIVClassic Map Server/Program.cs
#	FFXIVClassic Map Server/actors/Actor.cs
2016-06-18 05:59:42 +01:00
Tahir Akhlaq
1ad2b5d7d0 more work on commands
- moved script object to wrapper class to catch and log exceptions
- added loggers for basepacket/subpacket (todo: colour and use them in NLog.config)
- finished up most commands (todo: !property and !property2)
- todo: create and use mysql wrapper class to log exceptions
2016-06-18 05:42:14 +01:00
Filip Maj
4e69022072 New style of scripting for better complex menus. 2016-06-17 23:17:24 -04:00
Filip Maj
cdf4b3a2f2 GuildShop script done. 2016-06-16 22:44:50 -04:00
Tahir Akhlaq
57b9d5ab99 start of work moving commands to lua 2016-06-17 02:44:57 +01:00
Filip Maj
f4060e16bf Merged in xdemolish/ffxiv-classic-server/derp (pull request #15)
fixed derps causing client/server crashes
2016-06-16 14:20:40 -04:00
Tahir Akhlaq
ac01224769 fixed derps causing client/server crashes 2016-06-16 03:49:58 +01:00
Filip Maj
8eaa920751 Fixed logs on map. 2016-06-15 20:09:53 -04:00
Filip Maj
fbf6810c5c Fixed logs on lobby. 2016-06-15 20:06:08 -04:00
Filip Maj
9b3712044d Merged in xdemolish/ffxiv-classic-server/logging_and_casing (pull request #14)
moved stray console.writeline to use main logger
2016-06-15 14:22:05 -04:00
Tahir Akhlaq
1159c75ab8 moved stray console.writeline to use main logger 2016-06-15 19:15:24 +01:00
Filip Maj
1bac69c893 Fixed some startup output. 2016-06-15 10:40:30 -04:00
Filip Maj
9a29d0806a Merged in xdemolish/ffxiv-classic-server/logging_and_casing (pull request #13)
fixed logging and casing
2016-06-15 10:23:42 -04:00
Tahir Akhlaq
c413006a91 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into logging_and_casing
# Conflicts:
#	data/scripts/base/chara/npc/object/TaskBoard.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/baterich.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/claroise.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/flame_lieutenant_somber_meadow.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/gunnulf.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/heibert.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/ipaghlo.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/kokobi.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/mammet.lua
#	data/scripts/unique/wil0Town01/PopulaceStandard/roarich.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/dariustel.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/fruhybolg.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/guencen.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/hcidjaa.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/uwilsyng.lua
#	data/scripts/unique/wil0Town01a/PopulaceStandard/vavaki.lua
2016-06-15 04:41:15 +01:00
Tahir Akhlaq
2b81660dce accidentally mass replaced "target", fixed now 2016-06-15 04:27:25 +01:00
Tahir Akhlaq
884a26dc52 fixed method casing in lua 2016-06-15 03:41:23 +01:00
Filip Maj
c612b885dd Ul'dah npcs completed. 2016-06-14 21:47:54 -04:00
Tahir Akhlaq
ba13d5798d derp 2016-06-15 00:08:05 +01:00
Tahir Akhlaq
b633126568 fixed import script 2016-06-15 00:04:15 +01:00
Tahir Akhlaq
335a59204c Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server into method_casing
# Conflicts:
#	FFXIVClassic Map Server/CommandProcessor.cs
#	FFXIVClassic Map Server/WorldManager.cs
#	FFXIVClassic Map Server/actors/area/Area.cs
#	FFXIVClassic Map Server/actors/area/PrivateArea.cs
#	FFXIVClassic Map Server/actors/area/Zone.cs
#	FFXIVClassic Map Server/actors/chara/npc/Npc.cs
#	FFXIVClassic Map Server/common/Utils.cs
#	FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
2016-06-14 22:54:02 +01:00
Tahir Akhlaq
24f55139dd mass replaced all methods to pascal case 2016-06-14 21:29:10 +01:00
Tahir Akhlaq
ed0a0a58f7 added nlog logging (todo: custom logger for packets) 2016-06-14 19:06:55 +01:00
Filip Maj
f5619ff800 All of Limsa scripted. Ul'dah scripts auto generated. 2016-06-13 22:27:12 -04:00
Tahir Akhlaq
c5516511b0 cleaned up logging, added log_level param to enable/disable types of logging 2016-06-14 03:00:57 +01:00
Filip Maj
d1c8987091 Scripted almost all of lower limsa. 2016-06-13 21:26:19 -04:00
Filip Maj
65389e3362 Added scripts for the inn keepers. Added default event conditions to almost all actors. Updated sql for actorClass, spawnLocations, and new zoneEntrances. 2016-06-12 21:30:47 -04:00
Filip Maj
5723f77b1f Added all the new scripts for the actor instancing system. 2016-06-12 19:06:03 -04:00
Filip Maj
a4ea5f024b Merge branch 'actor_instancing' into develop
# Conflicts:
#	sql/gamedata_actor_class.sql
2016-06-12 18:52:30 -04:00
Filip Maj
fec348136e Merge branch 'master' into develop
# Conflicts:
#	FFXIVClassic Map Server/CommandProcessor.cs
2016-06-12 18:51:24 -04:00
Filip Maj
957a8d89bb Null event conditions get defaulted to empty conditions to allow anything to spawn. More work on the scripts. Committing the new sql schema + imports of all 3 town zones. 2016-06-12 18:43:41 -04:00
Tahir Akhlaq
c23f9c7ca9 PROJECT: added common library to make common files actually common
- renamed sln to FFXIVClassic.sln
- threaded logging
- todo: print packets using Log.Packet
2016-06-12 20:12:59 +01:00
deviltti
16d4779970 Fixed packet ByteArrayToHex output 2016-06-10 22:40:46 -04:00
deviltti
554c8b5514 Fixed packet Console output 2016-06-10 21:14:28 -04:00
deviltti
33a52c4fa8 Fixed derp in Console output 2016-06-10 20:17:35 -04:00
deviltti
1c712c7533 Cleaned up LogFile and ByteArrayToHex utils. 2016-06-10 19:58:01 -04:00
Filip Maj
f0d4429f65 Child scripts now loaded by a uniqueId in the spawn table. 2016-06-09 22:58:03 -04:00
Tahir Akhlaq
8b93abe86e servers now log (almost) everything to file
- regex'd in mysqlexception logging
- servers can now specify server_port, log_path, log_file
- added scripts to import/export all tables (exporting will export a handful of garbage table names, open and check for structure before deleting)
- fixed packet logging (thanks deviltti)
2016-06-09 19:48:06 +01:00
Filip Maj
23b6ede128 Designed the new script system for npcs. Added missing appearance info. 2016-06-09 00:46:17 -04:00
Filip Maj
92339ba0c4 Merged in xdemolish/ffxiv-classic-server (pull request #11)
fixed character create errors and..
2016-06-08 14:04:02 -04:00
Tahir Akhlaq
d486650143 fixed character create errors
import individual tables instead of one large sql file
2016-06-07 22:58:17 +01:00
Filip Maj
62d1fec8b3 README.md edited online with Bitbucket 2016-06-06 15:26:03 +00:00
Filip Maj
abbdaf1368 README.md edited online with Bitbucket, changed IRC server to Discord. 2016-06-06 15:24:57 +00:00
Filip Maj
fc51b7f564 Modified scripts to work with new system. 2016-05-29 16:03:24 -04:00
Filip Maj
62ed9b22f1 Implemented actor instancing, as well as automatic name generation for NPCs. 2016-05-29 15:14:09 -04:00
Filip Maj
f0ec2125ac Found out the second weather packet value is a transition time. 2016-05-09 22:19:57 -04:00
Filip Maj
b45390adb6 Fixed null worldManager due to it being set as a static variable at class creation. 2016-05-09 20:57:32 -04:00
Filip Maj
8df79c9e6f Modified the SetWeatherPacket. Second value is a toggle for instant or smooth transitions. 2016-05-09 20:48:18 -04:00
Filip Maj
78f2b18641 Merged in TheManii/ffxiv-classic-server (pull request #10)
Merge ingame_help part 3
2016-05-09 20:38:28 -04:00
TheManii
320d662abe Merge ingame_help_part_3 2016-05-09 18:30:57 -04:00
TheManii
6dcdabf9a4 Added more weather types 2016-05-09 16:58:04 -04:00
TheManii
c02c09a237 Bugfixed with !test 2016-05-09 01:15:58 -04:00
TheManii
59f1ef0594 REALLY fix whitepaces 2016-05-09 00:48:58 -04:00
TheManii
c80eb623b1 Fixed whitespaces 2016-05-09 00:48:16 -04:00
TheManii
a99a348c36 Added !help entries for !test weather 2016-05-09 00:40:46 -04:00
TheManii
101a2d50ed Fixed typo in !help 2016-05-09 00:26:53 -04:00
TheManii
11a371f32b Added !set weather <weathertype>and populated weather table 2016-05-09 00:23:35 -04:00
TheManii
2c18016a29 Merged master into ingame_help 2016-05-04 23:04:03 -04:00
Filip Maj
541456bd8e Fixed bug with warp. WorldManager cannot be statically stored like that. 2016-04-24 17:59:50 -04:00
TheManii
a7959d9263 Merged Ioncannon/ffxiv-classic-server into master 2016-04-20 13:50:01 -04:00
Ioncannon
9e2960c047 Merged in TheManii/ffxiv-classic-server (pull request #9)
Make post build not fail due to modified files/silently ignore updated files
2016-04-18 16:23:55 -04:00
TheManii
01dd955376 Wrong flag 2016-04-18 15:47:57 -04:00
TheManii
426750f931 Make post build not fail due to modified files/silently ignore updated files 2016-04-18 15:42:17 -04:00
Ioncannon
c944d262b3 Merged in TheManii/ffxiv-classic-server (pull request #8)
Merge web_part_1
2016-04-18 13:49:46 -04:00
Filip Maj
7827fbf8d3 Took out some test code for the limsa opening script. 2016-04-18 13:44:51 -04:00
Filip Maj
d01c780cac Latest sql files. Also the gamedata ones were split from the main core. 2016-04-18 13:43:09 -04:00
Filip Maj
ffae2b744f Untracked the ./scripts folder since it was moved to ./data/scripts 2016-04-18 13:35:10 -04:00
Filip Maj
53064a7345 All the script changes done to get the openings working. 2016-04-18 13:33:31 -04:00
Filip Maj
3d5fa45730 Merge branch 'develop'
# Conflicts:
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
#	FFXIVClassic Map Server/Server.cs
#	data/scripts/player.lua
#	scripts/zones/193/npcs/pplStd_11@0C100.lua
2016-04-18 13:31:55 -04:00
Filip Maj
79eaf5d79e Added more quest functions and completed the scripts for Gridania and most of Ul'dah. Up to the battle part that is. 2016-04-17 19:09:01 -04:00
TheManii
4a8b241e4e Merged Ioncannon/ffxiv-classic-server into master 2016-04-16 23:11:42 -04:00
TheManii
20427400ef Merge web_part_1 into master 2016-04-16 23:10:46 -04:00
Filip Maj
95849e1c1c onInit was added to all the scripts. Added code for all the Limsa opening event npcs. 2016-04-14 08:31:39 -04:00
Filip Maj
bd4e4a293c Removed a buffer being created for no reason. 2016-04-14 08:30:34 -04:00
Filip Maj
d989ec2a58 Added two callbacks to the Director; onTalked and onCommand. Split the command and event starts and keep track of them separately. 2016-04-14 08:30:21 -04:00
TheManii
14a7a4172a Added rest of fields, chocobo fields are disabled as they dont work if there is no chocobo entries for a character 2016-04-14 03:44:05 -04:00
Filip Maj
108f5aa677 Fixed crash due to bad constructor for QuestDirectorMan0L001. Unsigned integers will also write out as lua 0-datatype. 2016-04-11 22:49:05 -04:00
TheManii
863e006830 Converted initial profile + appearence to new db schema, currently only read only due to submit functions being unmodified 2016-04-11 17:00:26 -04:00
TheManii
e33bd05f09 Removed wrong files 2016-04-11 14:40:08 -04:00
TheManii
c9838254b9 Revert "Remove unused files"
This reverts commit 1ce34914bc.
2016-04-11 14:39:33 -04:00
TheManii
1ce34914bc Remove unused files 2016-04-11 14:35:17 -04:00
TheManii
73d5b9fbf1 Use intra-zone warps for !warp relative 2016-04-11 14:33:18 -04:00
Filip Maj
fe111ab6ca Quest data is now saved/loaded from the DB. 2016-04-10 13:11:12 -04:00
Ioncannon
de7484a931 Merged in TheManii/ffxiv-classic-server (pull request #7)
Merge ingame_help part 2
2016-04-10 11:17:37 -04:00
Filip Maj
b8a3d4f1e0 Added quest director class. 2016-04-10 11:14:36 -04:00
TheManii
44650bc4a5 Merge from master 2016-04-09 13:27:50 -07:00
TheManii
02e9b52a02 Fix typo 2016-04-09 13:26:46 -07:00
TheManii
10d4d7c148 Merge in Relative warps 2016-04-09 12:42:24 -07:00
TheManii
5c7ca212aa 2nd half of previous commit 2016-04-09 12:38:15 -07:00
TheManii
c38fbc0c09 *Revert ea1e16a, should be done globally and not simply here 2016-04-09 12:35:29 -07:00
TheManii
06606c5f01 *Revert changes to worldmanager.cs, not needed anymore
*Made !warp silently catch all exceptions so they dont crash server/don't change player state if invalid
*Moved rest of !warp parsing logic into parseWarp(), doWarp() now purely handles actual act of warping
2016-04-09 12:27:04 -07:00
TheManii
2eb40a0d7c Save player rotation for relative warps
Make !warp more robust with error handling
2016-04-09 11:28:21 -07:00
TheManii
b1a9ced93e Merged master into ingame_help 2016-04-08 13:07:20 -04:00
TheManii
dbbd1fa0d8 Fix merge 2016-04-08 10:03:35 -07:00
TheManii
de2ec984e4 Revert "Fix merge"
This reverts commit 29228a0c11.
2016-04-08 09:59:56 -07:00
TheManii
29228a0c11 Fix merge 2016-04-08 09:57:40 -07:00
TheManii
5920d93b19 Merged master into ingame_help 2016-04-08 12:51:28 -04:00
TheManii
3790920db3 Typo 2016-04-08 00:51:34 -07:00
TheManii
21745a6aa8 Added relative warps 2016-04-08 00:48:34 -07:00
TheManii
574b2da4f8 Merged Ioncannon/ffxiv-classic-server into master 2016-04-08 01:37:37 -04:00
TheManii
fc07d2e24d Merge ingame_help into master 2016-04-07 22:25:58 -07:00
TheManii
33be97ea9d Make CommandProcessor more robust 2016-04-07 22:22:31 -07:00
Filip Maj
c0cd7555e1 -Fixed up the quest flag functions.
-Renamed the ActorSpecialGraphicPacket to SetActorQuestGraphic as those icons all have to do with questing.
-Got onSpawn to work and implemented the quest graphics.
-Added new QuestDirector class.
2016-04-07 22:34:10 -04:00
Filip Maj
1f5788def8 Redundent zoneid was redundent. 2016-04-07 22:32:04 -04:00
TheManii
cc5d0b139a Added new !warp to help 2016-04-07 12:29:17 -07:00
TheManii
ecc61ea5f9 Surrounded command chain with region boxes
Changed doWarp() to handle in implicit, in-zone only warps

Might have issues with instanced zones, untested
2016-04-07 12:25:28 -07:00
TheManii
b17d193a59 Fix previous commit 2016-04-07 11:41:56 -07:00
TheManii
7c0594b749 Cherrypick *b16ea7b Disable login10/11 2016-04-07 10:37:14 -07:00
Ioncannon
8b55993f25 Merged in TheManii/ffxiv-classic-server (pull request #5)
Disable login10/11
2016-04-07 13:23:44 -04:00
TheManii
b16ea7bc44 Disable login10/11 2016-04-07 10:21:04 -07:00
TheManii
4cf005467a Moved most of the strings to external resource file 2016-04-06 19:55:12 -07:00
TheManii
cd8cb1acb3 Made give/removecurrency consistant with help description 2016-04-06 16:28:24 -07:00
TheManii
26f5e1be28 Fix spelling 2016-04-06 15:34:04 -07:00
TheManii
ea1e16aea7 Make Getters more case consistant 2016-04-06 15:29:24 -07:00
TheManii
cdcdd6a584 Split off ingame commands from server 2016-04-06 15:22:26 -07:00
TheManii
c74e40f7d0 Merge 23aef8c Removed need for the login2.bin packet file.
Merge 49a4bf1 Fixed the SQL schema to work with the map server as well as updated the server id in the config file to match that in the database
2016-04-06 10:51:12 -07:00
TheManii
cb86bcb3af Merged Ioncannon/ffxiv-classic-server into master 2016-04-06 13:47:59 -04:00
Ioncannon
dabbff1fda Merged in TheManii/ffxiv-classic-server (pull request #3)
Simplify post build steps
2016-04-06 13:40:45 -04:00
Ioncannon
77c12c489c Merged in VeryCrushed/ffxiv-classic-server (pull request #4)
Fixed the SQL schema to work with the map server as well as updated the server id in the config file to match that in the database
2016-04-06 13:39:52 -04:00
Andrew Babbitt
49a4bf1ab0 Fixed the SQL schema to work with the map server as well as updated the server id in the config file to match that in the database 2016-04-05 23:52:16 -06:00
TheManii
1ef3e350c0 Fix line endings 2016-04-05 16:13:16 -07:00
TheManii
7a8e53a8ac Add in ingame help system 2016-04-05 16:06:38 -07:00
TheManii
5892887e4c Merged Ioncannon/ffxiv-classic-server into master 2016-04-05 18:33:46 -04:00
Filip Maj
23aef8cc46 Removed need for the login2.bin packet file. 2016-04-05 17:34:34 -04:00
TheManii
9a2977a094 Merge branch 'master' of https://TheManii@bitbucket.org/TheManii/ffxiv-classic-server.git 2016-04-05 13:03:47 -07:00
TheManii
1a43f15800 Fix partial copies post compile 2016-04-05 13:03:46 -07:00
TheManii
aa4fc09a32 Revert "Remove unused files/docs that belong on wiki"
This reverts commit 64155dc752.
2016-04-05 11:43:12 -07:00
TheManii
64155dc752 Remove unused files/docs that belong on wiki 2016-04-05 11:42:17 -07:00
TheManii
8cb1ae99e8 README.md edited online with Bitbucket 2016-04-05 18:22:32 +00:00
TheManii
f8a2b7efc7 Update .gitignore for user provided data 2016-04-05 11:19:23 -07:00
TheManii
5d3f25f1a8 Don't Clobber existing files 2016-04-05 11:08:02 -07:00
TheManii
ddf4d0d202 Consolidated server data and automatically place them in approporate directories post build 2016-04-05 10:42:42 -07:00
Filip Maj
b68d13ea7f Cleaned up the lua calls and renamed "onInstantiation" to "init". Added a "onSpawn" callback but still working on it. Added the "ActorSpecialGraphicPacket" and functions to use it. 2016-04-02 17:56:01 -04:00
Filip Maj
e501d5b796 Merge branch 'develop' 2016-04-01 23:50:29 -04:00
Filip Maj
4c391f64bc Removed old inn code and realigned all the cutscene flags. Offsets will need to be figured out again though. 2016-04-01 23:50:17 -04:00
Filip Maj
ae9a712477 Added scripts for all the npcs (minus the door) in the Limsa Opening zone (boat). The beginning tutorial stuff is also scripted. 2016-04-01 23:32:52 -04:00
Filip Maj
91842ab08a Merge branch 'develop'
# Conflicts:
#	FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
2016-04-01 23:27:34 -04:00
Filip Maj
1dd04e2174 Merge branch 'director_and_questing' into develop 2016-04-01 23:24:28 -04:00
Filip Maj
6c3918ac2f Got the kick event packet working and implemented the director parameter in the player instantiation. The first argument of the set event status packet is an "isEnabled" flag; switched to bool rather than int. 2016-04-01 23:24:14 -04:00
Filip Maj
cf73522291 Reversed change to output folder that was done in previous pull request merge. 2016-03-30 20:49:37 -04:00
Filip Maj
8da3a6ff9c Merge branch 'develop'
# Conflicts:
#	FFXIVClassic Map Server/packets/send/Actor/events/SetEmoteEventCondition.cs
2016-03-30 20:18:28 -04:00
Filip Maj
60b4035ec5 Receive routine in the lobby server now checks if bytes read is > (not >=) than 0. This was causing connections to stay active and cause the CPU to get bogged down. 2016-03-30 20:16:59 -04:00
Filip Maj
597a800599 More work trying to get the opening cutscene to fire right away. 2016-03-30 20:15:21 -04:00
Ioncannon
48b9fa39b5 Merged in VeryCrushed/ffxiv-classic-server (pull request #1)
Small Fixes
2016-03-30 11:06:17 -04:00
Andrew Babbitt
52806d2f3d Updated the readme to be more helpful. 2016-03-29 17:52:37 -06:00
Andrew Babbitt
eaafba79e2 Updated .gitignore and changed all projects to build in a central directory at the root of the project. 2016-03-29 17:38:41 -06:00
Filip Maj
6124e6906d Uploaded a template config.ini file. 2016-03-29 17:30:51 -04:00
Filip Maj
48f1fbc8f5 Implemented the emote and notice event conditions. 2016-03-29 17:09:16 -04:00
Filip Maj
1dccc0530e Static actor file can be now loaded from the original encrypted script in the FFXIV folder. This way I do not run into issues of sharing client files. 2016-03-28 23:05:19 -04:00
Filip Maj
94db8336df Added login site. 2016-03-28 22:07:10 -04:00
Filip Maj
b33b0b1bc4 When zoning into a inn, cutscene packet will be sent as well. 2016-03-28 22:00:11 -04:00
Filip Maj
b69e18ff3c Companion name was off by 1. 2016-03-28 21:52:02 -04:00
Filip Maj
a615f29e63 Added path companion data to the cutscene book packet. Now that packet will fire if zoning into the inn. Removed some debug logs. Removed a duplicate zone packet send call. 2016-03-28 21:00:33 -04:00
Filip Maj
4d57aa72a6 Cleaned up the 0x02 packet. It fires in response to the 0x2 packet sent by the client it seems. 2016-03-28 12:14:10 -04:00
Filip Maj
a30311d12a Added director related code to player and packet processor. Cleaned up some debug messages. Added a flag when a player is "zoning in". 2016-03-28 11:31:21 -04:00
Filip Maj
f8ab0cd86d Added langauge code packet (0x6) and 0x2/0x7 temp packets to clean up the login packets sent by client. 2016-03-28 11:30:02 -04:00
Filip Maj
9c28e966f7 Added director code to player class and actor namespace. 2016-03-23 01:27:12 -04:00
Filip Maj
49a13effca Fleshed out the quest actor and added a place to store the current active quest actors in the Player actor. 2016-03-21 11:42:27 -04:00
Filip Maj
3162bedb17 Added trigger name to all the scripts that had params. Implemented the Gridania opening stoper. 2016-03-20 21:19:40 -04:00
Filip Maj
2048d8d188 Implemented a intra-zone teleport. Trigger Name is now sent to to the "eventStart" lua callback. Lua scripts can now access world manager. 2016-03-20 21:18:46 -04:00
Filip Maj
08fd862939 Implemented the emote and notice event conditions. 2016-03-20 19:34:39 -04:00
Filip Maj
0876b293e8 Started to implement private areas. Works mostly, but only one instance is created. All the push triggers work more or less except bounding box. 2016-03-20 19:29:38 -04:00
Filip Maj
67fed3dba5 Fixed bug where new characters would not have items equipped. This was due to the slotId was being saved, not the unique itemId. 2016-03-20 12:43:20 -04:00
Filip Maj
1417a0d841 Pushed the latest sql import file. 2016-03-20 12:30:29 -04:00
Filip Maj
01ba37c50d Added hair variation to the db. Turned out the hair highlight color was mis-sized (1 byte not 2) causing an invalid number when a variation was there. 2016-03-20 12:18:41 -04:00
Filip Maj
d80e9bed0e Added new DB changes to character creator. Overhauled the get character methods to include as much data as possible. Fixed an issue with undergarments not being set properly for certain race/classes. 2016-03-20 11:49:09 -04:00
Filip Maj
d9bccb5bff Fixed bug in equip script causing the classChange function to be called multiple times due to classId not being a local variable. Added some test scripts for Request Information/QuestJournal Command. 2016-03-19 19:22:28 -04:00
Filip Maj
335ec414d6 Levels are now loaded in from the database, and "mainSkillLevel" properties are also correctly set. 2016-03-19 19:21:16 -04:00
Filip Maj
1f60bcf4fc Finished code to send character skill (class) info. Added parameterdata request packet that requests this info. 2016-03-19 18:43:02 -04:00
Filip Maj
d2a5eaa2c8 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server 2016-03-19 10:23:20 -04:00
Filip Maj
a93843510e Cleaned up script packets and added the InfoResponse packet (internally the DataPacket). Added more info to the music packets. More work on class changing. 2016-03-19 10:22:20 -04:00
Filip Maj
6ef28e590c Folder rename: FFXIVClassic_Lobby_Server to FFXIV Classic Lobby Server. 2016-03-17 14:33:58 -04:00
Filip Maj
81abefcf39 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-server 2016-03-16 17:34:54 -04:00
Filip Maj
e4c296ca7e Cleaning up one more dependency. 2016-03-16 17:33:57 -04:00
Ioncannon
d4a3b601fa README.md edited online with Bitbucket 2016-03-16 21:21:42 +00:00
Filip Maj
c91e0ef146 Updated Newtonsoft JSON dependency in lobby server. 2016-03-16 17:13:33 -04:00
Filip Maj
3ece02932f Removed tracked packages. VS will restore new packages on first open. 2016-03-16 17:10:38 -04:00
Filip Maj
f92d9ea2f3 Added lobby to the solution. Cleaning up dependencies. 2016-03-16 17:07:48 -04:00
Filip Maj
978f31e64a Merged the master branch of the Lobby server repo, into the map server repo. There is no reason to have two separate repos and the lobby server project will be now under the whole FFXIV Classic VS solution. 2016-03-16 14:53:00 -04:00
Filip Maj
01eceee58f Smallclothes equipment are now saved under the "Adventurer" class as they are a separate thing from classes. 2016-03-12 10:54:08 -05:00
Filip Maj
f71b4ef031 Fixed bug where DB writing for equipment would be toggled off if gearset was nil for some reason. Added in a property change to get the bottom class icon to refresh showing the new class. 2016-03-12 10:01:41 -05:00
Filip Maj
e409d3792c Scripts for running the various commands/npcs (done so far) are pushed. 2016-03-12 02:54:03 -05:00
Filip Maj
e851c767df Finished check command as well as gearsets and switching between classes. Property changes still have to be written though. 2016-03-12 02:52:34 -05:00
Filip Maj
44e5430fdc Implemented equipment and equip graphics. Add some zone callbacks and "first start" functionality. Added playtime. 2016-03-06 17:55:42 -05:00
Filip Maj
88cb73bc09 Blowfish key is now generate from client's handshake packet. 2016-03-05 18:02:37 -05:00
Filip Maj
c9116005d6 Changed untradeable to itemType (since it's used for bazaar as well). 2016-02-22 22:33:52 -05:00
Filip Maj
83fb9badd7 Finished writing the query and editing the inventory methods to use the gamedata. 2016-02-21 21:44:11 -05:00
Filip Maj
4bebeb387a Fixed use to isUsable in utility function. 2016-02-21 20:48:54 -05:00
Filip Maj
0e4b9f4263 Finished writing final datastructure for items. Did some cleanup in server. 2016-02-21 20:48:07 -05:00
Filip Maj
e72f1d3dcf Finished the structure of the database item loader. Added the graphics portion of the reader. 2016-02-21 16:34:29 -05:00
Filip Maj
2f3f677ec4 Wrote item loaders for gamedata. 2016-02-21 16:13:35 -05:00
Filip Maj
d66d2908ec Added in all the utility functions from the Item script. 2016-02-21 15:00:49 -05:00
Filip Maj
d2ac603efa Renamed the "Item" object to InventoryItem. Began writing the Item object that will be used to store game data items. 2016-02-21 14:06:23 -05:00
Filip Maj
c2f0b9d999 Equipment now working. Still need to write database saving/loading. 2016-02-20 21:20:54 -05:00
Filip Maj
b7fd3e442c Added 0x6c to the actorIdChanger. Mount appearance is now broadcast to show Goobbue. Equipment packets implemented as well as Equipment object. 2016-02-20 16:51:35 -05:00
Filip Maj
5acc769505 The correct appearance is now set depending on what class you choose in chara creator. The actual items will be added in by the map server. The appearance is handled by the lobby in the case the user successfully makes a character, but never logs into the server (due to a disconnect or something). 2016-02-20 11:20:59 -05:00
Filip Maj
d5f07b97a8 Added a cleanup thread to delete any disconnected connections. 2016-02-20 00:38:32 -05:00
Filip Maj
1c5f8b3d0b Fixed a character appearance bug when making a character. Current zone now shown. Added a utility for setting new gear appearance. 2016-02-20 00:11:51 -05:00
Filip Maj
23dcc1dafe Reorganized the packets to follow the format the map server follows. 2016-02-18 23:55:03 -05:00
Filip Maj
a47d5f96a5 Fixed emotes not being sent to the emoter. Fixed appearance packets' gloves/legs being ordered wrong. Chat is implemented. Changed commands to start with '!'. 2016-02-18 22:38:54 -05:00
Filip Maj
8c73f6e926 Ported over the network code from the map server. A lot of backedlogged changes are here as well. 2016-02-16 23:35:21 -05:00
Filip Maj
c6ac8b2f14 Fixed an error in the netcode that would cause the client to d/c on partial packets. Set buffer size to 0xFFFF due to disconnect on really large packets (ie gm packet). Implemented support ticket packets. 2016-02-16 22:53:53 -05:00
Filip Maj
cb4171f1fd Bunch of bugfixes and final tweaking to get inventory working. 2016-02-14 12:09:18 -05:00
Filip Maj
47be08fbf7 Finished remove item code. Inventory Add/Remove should be complete. 2016-02-13 22:25:40 -05:00
Filip Maj
110a112328 Implemented remove though will need to test more. Finished tweaking addItem(itemId, quantity). 2016-02-13 21:14:49 -05:00
Filip Maj
73732ac542 Fully implemented Lua Param Data Type 9. 2016-02-13 16:39:33 -05:00
Filip Maj
1f3cd8eaf3 Added the two new datatypes to get the inventory commands to parse properly. 2016-02-13 16:33:33 -05:00
Filip Maj
69b34fdce7 Reworked the inventory system so that each inventory type is contained in it's own "Inventory" object. Also, fixed the Inventory packets being all malformed. 2016-02-13 14:12:05 -05:00
Filip Maj
df2ac1fb32 Added all the inventory packets, and implemented add and get inventory from the db to the server. Inventory at login is now connected to the db! 2016-02-11 22:14:40 -05:00
Filip Maj
c4dea467e3 Fixed missing seek, added battle packet 0x13C. 2016-02-07 15:43:32 -05:00
Filip Maj
0d880b6b75 Figured out most of the battle action packets; 0x139, 0x13a, 0x13b. 2016-02-07 15:28:08 -05:00
Filip Maj
6d8064aa6c Began work on the battle action packet. 2016-02-07 13:06:04 -05:00
Filip Maj
42ba95b69d Reworked zones to allow for isolated zones (IE Opening Zone) and private area instances. 2016-02-07 13:05:54 -05:00
Filip Maj
c83b4a12b9 Added the game message packets. Fixed "canRideChocobo" param in zone not working. Added a lot more function for lua to access. Various minor changes. 2016-02-03 00:45:11 -05:00
Filip Maj
cfb29b912f Speed is now stored in the actor. Redid actor speed packet to use float. Added GameMessagePacket which can use all 20 msg packets. Added functions for lua side to call in player obj. 2016-02-02 00:02:06 -05:00
Filip Maj
fe69f069ea Lua Parameter type 0 is now signed int. Type 1 in unsigned int. ShopSalesman script uses signed. 2016-01-31 12:23:12 -05:00
Filip Maj
45b9f9a064 Looked at pong packet once again. First 32bits are resent of incoming ping packet. Next 16bits always 0x14D. Heard from another dev this may improve movement for multiplayer. 2016-01-28 23:25:11 -05:00
Filip Maj
5c8277fbb9 Redid the database, actor_class and npclist was combined. Added commands to the lua engine. Script will default to a PopulaceStandard if no script detected to avoid crashing. Static Actors now loaded from the static actors file. 2016-01-28 23:24:20 -05:00
Filip Maj
789df97d48 More static actors loaded and can be accessed anywhere. Improved lua scripting to allow small talk. 2016-01-25 01:10:43 -05:00
Filip Maj
300748668f Removed NLua and replaced it with MoonSharp. Scripting for NPCs has been implemented, but still have to test a lot. 2016-01-24 17:11:35 -05:00
Filip Maj
74be19c51d Moved lua engine into server. 2016-01-24 10:32:37 -05:00
Filip Maj
e043be5ca4 Added a way to reset a zone and reload the NPC list. 2016-01-24 03:10:17 -05:00
Filip Maj
f1025f89d3 Rewrote the server commands. They can now accept a client connection, letting a user fire a command from within the game and only receive the response. Added actor removal for the instance system. Removed hardcoded packet 9. 2016-01-23 23:28:12 -05:00
Filip Maj
7bc3c8c2dd Added event conditions to the database. This is a JSON object that stores all types of conditions. The server also sends the correct packets to enable these conditions (minus the push packets... those aren't implemented). 2016-01-23 22:11:45 -05:00
Filip Maj
3b48ed1f74 Added actor event packets. 2016-01-23 20:12:04 -05:00
Filip Maj
ea6b1e33c7 NPCs now spawn and load template from the db. 2016-01-20 23:18:10 -05:00
Filip Maj
02b90edd3f Added two new commands; warp by zone entrance and a getpos command. Fixed character actor not appearing on zone... 0x2 packet only sent on login. Added spawnType to getSpawnPackets. 2016-01-20 00:02:57 -05:00
Filip Maj
3fcc9eea49 Moved the warp and send packet code out of packet processor and into the server object. Rewrote the warp command to use the world manager (still working on it). Add a playmusic command. 2016-01-19 22:07:29 -05:00
Filip Maj
d90dc0cb80 Redid the initial handshake code to handle the found connection type field. Server should no longer create two player objects and code has been reduced. Removed instances of connection1/2 getters... server simply sends packets down zone connection. Fixed issue with world manager not zoning in player due to missing 0x2 packet. 2016-01-19 21:47:59 -05:00
Filip Maj
093d3b7c15 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxiv-classic-map-server 2016-01-19 21:06:50 -05:00
Filip Maj
0462b790b7 Built a WorldManager to handle zones. 2016-01-19 21:06:41 -05:00
Filip Maj
5d11a0b356 Changed isEncrypted to isCompressed in basepacket. After speaking with another dev, game packets are not encrypted... just compressed. Figured out that byte 3 of basepacket is the connection type when handshaking with the map server. 2016-01-19 13:31:24 -05:00
Filip Maj
887da7b503 Moving zone/login stuff away from packetprocessor into a "WorldManager" class. 2016-01-17 23:36:34 -05:00
Filip Maj
a640e08fe1 Merge branch 'scripting' 2016-01-17 11:54:27 -05:00
Filip Maj
db62b05fdc Merge branch 'database_work' into scripting
# Conflicts:
#	FFXIVClassic Map Server/actors/chara/Character.cs
#	FFXIVClassic Map Server/actors/chara/npc/Npc.cs
#	FFXIVClassic Map Server/actors/chara/player/Player.cs
2016-01-17 11:53:52 -05:00
Filip Maj
d77344b725 Multiple zones are now stored on the server and accessed properly. 2016-01-17 11:48:55 -05:00
Filip Maj
0e85e2bddf Implementing zone settings from DB. 2016-01-17 01:51:02 -05:00
Filip Maj
9d67718060 Added utils to generate sql tables from game data. 2016-01-17 01:50:38 -05:00
Filip Maj
1c845e62e3 Implemented WeatherDirector , ZoneMaster, and WorldMaster in code. Zone objects has become the ZoneMaster actor object. 2016-01-16 23:03:04 -05:00
Filip Maj
724445a54a Achievements are now loaded from the database. Cleaned up login packets. 2016-01-16 18:38:49 -05:00
Filip Maj
f7702bca13 Added some new work parameters. Fixed GC Packet (wrong sized data). Connected player data packets to DB. Cleaned up login code. 2016-01-16 11:26:35 -05:00
Filip Maj
2bf532a6db Fixed bug in property reflection code. If array had 2 or more digit index, would truncate to 1 digit. 2016-01-12 01:20:09 -05:00
Filip Maj
e47904dc30 Got commands working. Wrong ID for one of em. 2016-01-12 00:43:52 -05:00
Filip Maj
aebaa1b70e Changed param constants. 2016-01-10 23:21:06 -05:00
Filip Maj
d9e274eb09 Quests and Leves now load from the db. 2016-01-10 14:15:46 -05:00
Filip Maj
5b5b99bb4b Got most of the properties getting set. Commands and General Parameters broken. 2016-01-10 13:36:36 -05:00
Filip Maj
d42dac543f Fixed wrong values sent for the setactorproperty packet. Initialized commandSlot_compatibility which was null. 2016-01-10 11:47:22 -05:00
Filip Maj
156f8e1e7d Added get init packets to packet processor. 2016-01-10 03:09:01 -05:00
Filip Maj
bea796ec85 Removed old db stuff. 2016-01-10 03:05:22 -05:00
Filip Maj
625ee299f7 Added more defaults. 2016-01-10 02:59:16 -05:00
Filip Maj
3205bd1c83 Added property init function which should get everything working. Added defaults to some properties. 2016-01-10 02:44:32 -05:00
Filip Maj
44c45c4ad2 Cleanup. 2016-01-09 21:35:45 -05:00
Filip Maj
524b57ed30 stop tracking this 2016-01-08 23:40:01 -05:00
Filip Maj
af4a0d5546 Changing how appearance works, pulled from a DB now. 2015-10-05 19:37:03 -04:00
Filip Maj
ad0cfca160 Added missing dapper package stuff. 2015-10-02 22:40:51 -04:00
Filip Maj
0c1d993b32 Removed old Blowfish DLL project, added server position to server research doc. 2015-10-02 22:39:38 -04:00
Filip Maj
2f98046d15 Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxivclassic-lobby-server 2015-10-02 22:37:44 -04:00
Filip Maj
6e33f39ae2 Removed packets since all lobby stuff is done and these are map server related. 2015-10-02 22:37:08 -04:00
Filip Maj
82ec583528 Removed Blowfish from solution. 2015-10-02 19:03:43 -04:00
Filip Maj
733c857c3f Blowfish reimplemented in C#, get's rid of the dll dependency allowing server to be run on Linux (Mono) as well. 2015-10-02 19:03:07 -04:00
Filip Maj
3796bd3ebe Midlander Male model id wasn't being set properly. 2015-09-14 00:19:52 -04:00
Filip Maj
0f711ab694 Fixed wrong state numbers due to removing the "Deleted" state. 2015-09-13 21:30:54 -04:00
Filip Maj
ddf1d2d1a3 Added account and select character packet creators. Fixed wrong field being read for session id. Most of the server is now NOT hardcoded and customizable from the DB. Only hardcoded packet left is the initial handshake. 2015-09-13 18:21:41 -04:00
Filip Maj
caf3968e5b All appearance data seems to be working now. Equip model ids are sent but not set, so body is invisible. Figuring out how to handle this. 2015-09-13 14:12:41 -04:00
Filip Maj
9c4220bfd2 Chara info is now generated and sent without errors. Still need to figure out what equip IDs to use, and add face and characteristics data. 2015-09-13 11:56:48 -04:00
Filip Maj
d9302db3a0 Removed uneeded packets since they have been implemented programmatically. 2015-09-13 11:31:21 -04:00
Filip Maj
b717f6aeb1 Character deletes now delete the character from the DB instead of just changing the state. DB can now get single character. Character list is sent properly as per how 1.0 did it (only 1 'NEW' entry if available). Character info is now loaded from the new character packet and stored. It is also loaded for each character, encoded, and displayed (still testing). 2015-09-13 11:30:33 -04:00
Filip Maj
aadca3968d Merge branch 'master' of https://bitbucket.org/Ioncannon/ffxivclassic-lobby-server
Conflicts:
	FFXIVClassic_Lobby_Server/packets/CharacterListPacket.cs
2015-09-11 18:59:08 -04:00
Filip Maj
d6ec5e7240 Added all Console writes to the log. Put in "Max chars" for character list. 2015-09-11 18:57:22 -04:00
Filip Maj
d96f5be7ac Fixed the "end of list" byte. Think character lists should work. 2015-09-11 18:53:32 -04:00
Filip Maj
e90a25d0ab Replace ini file reader with full .NET implementation so it can run on Mono. 2015-09-10 19:00:44 -04:00
Filip Maj
d90cf6d953 Import and Retainer lists now sent. 2015-09-10 00:52:31 -04:00
Filip Maj
443212830a Finished character creator DB calls, moved DB stuff to Dapper, started work on get characters. 2015-09-09 00:08:46 -04:00
Filip Maj
9dfd6906b9 Added log code. 2015-09-08 19:39:52 -04:00
Filip Maj
7834b737eb Added sleep to packet thread to avoid cpu consumption. 2015-09-08 00:52:19 -04:00
Filip Maj
f566c14ea0 Fixed "getServer" bug in DB class. Cleaned up chara creator function. Fixed bug in error packet. 2015-09-08 00:42:02 -04:00
Filip Maj
754f14862a Finished the character creator packets. Worked on the character list packets. 2015-09-07 23:43:23 -04:00
Filip Maj
c78414f9be Added temp character and retainer packets. Added constants for easy modding. 2015-09-07 12:12:08 -04:00
Filip Maj
6c869353cc World list packet fixes, and worked on reserve packet. 2015-09-03 23:07:56 -04:00
Filip Maj
e7e267bd44 Reimplemented server list using BInaryWriter. 2015-09-03 22:20:53 -04:00
Filip Maj
a65e81273b Server list is now sent from db rather than hard coded. 2015-09-03 01:02:55 -04:00
Filip Maj
091166b41a Error and server list packets added. Reserve will send error to client if a character name is take for a server. Code to send out server list on GetCharacters added. 2015-09-02 14:07:45 -04:00
Filip Maj
c982493d66 Added all the packet files used for testing. 2015-08-27 10:27:54 -04:00
Filip Maj
f996f727dc Server now processes session ids and stores the correct logged in user in the clientconnection object. Reserve character now creates a entry in the db. 2015-08-27 10:19:00 -04:00
Filip Maj
c1e214175f Initial commit of the FFXIV 1.0 lobby server. 2015-08-26 13:38:58 -04:00
1285 changed files with 134761 additions and 64274 deletions

219
.gitignore vendored
View File

@@ -1,4 +1,215 @@
FFXIVClassic Map Server/bin/Debug/packets/wireshark packets/
FFXIVClassic Map Server/bin/
FFXIVClassic Map Server/obj/
config.ini
# Ignore files obtained from game client
/data/staticactors.bin
/data/packets/login/login*.bin
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
## TODO: Comment the next line if you want to checkin your
## web deploy settings but do note that will include unencrypted
## passwords
#*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml

View File

@@ -0,0 +1,477 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Ionic.Zlib;
using NLog;
using NLog.Targets;
namespace Meteor.Common
{
[StructLayout(LayoutKind.Sequential)]
public struct BasePacketHeader
{
public byte isAuthenticated;
public byte isCompressed;
public ushort connectionType;
public ushort packetSize;
public ushort numSubpackets;
public ulong timestamp; //Miliseconds
}
public class BasePacket
{
public const int TYPE_ZONE = 1;
public const int TYPE_CHAT = 2;
public const int BASEPACKET_SIZE = 0x10;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public byte[] data;
public BasePacketHeader header;
//Loads a sniffed packet from a file
public unsafe BasePacket(string path)
{
var bytes = File.ReadAllBytes(path);
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
if (packetSize - BASEPACKET_SIZE != 0)
{
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
else
data = new byte[0];
}
//Loads a sniffed packet from a byte array
public unsafe BasePacket(byte[] bytes)
{
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
public unsafe BasePacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
int packetSize = header.packetSize;
if (bytes.Length < offset + header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, offset + BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
offset += packetSize;
}
public BasePacket(BasePacketHeader header, byte[] data)
{
this.header = header;
this.data = data;
}
public List<SubPacket> GetSubpackets()
{
var subpackets = new List<SubPacket>(header.numSubpackets);
var offset = 0;
while (offset < data.Length)
subpackets.Add(new SubPacket(data, ref offset));
return subpackets;
}
public static unsafe BasePacketHeader GetHeader(byte[] bytes)
{
BasePacketHeader header;
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
return header;
}
public byte[] GetHeaderBytes()
{
var size = Marshal.SizeOf(header);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetPacketBytes()
{
var outBytes = new byte[header.packetSize];
Array.Copy(GetHeaderBytes(), 0, outBytes, 0, BASEPACKET_SIZE);
Array.Copy(data, 0, outBytes, BASEPACKET_SIZE, data.Length);
return outBytes;
}
//Replaces all instances of the sniffed actorID with the given one
public void ReplaceActorID(uint actorID)
{
using (var mem = new MemoryStream(data))
{
using (var binWriter = new BinaryWriter(mem))
{
using (var binreader = new BinaryReader(mem))
{
while (binreader.BaseStream.Position + 4 < data.Length)
{
var read = binreader.ReadUInt32();
if (read == 0x029B2941 || read == 0x02977DC7 || read == 0x0297D2C8 || read == 0x0230d573 ||
read == 0x23317df || read == 0x23344a3 || read == 0x1730bdb || read == 0x6c)
//Original ID
{
binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin);
binWriter.Write(actorID);
}
}
}
}
}
}
//Replaces all instances of the sniffed actorID with the given one
public void ReplaceActorID(uint fromActorID, uint actorID)
{
using (var mem = new MemoryStream(data))
{
using (var binWriter = new BinaryWriter(mem))
{
using (var binreader = new BinaryReader(mem))
{
while (binreader.BaseStream.Position + 4 < data.Length)
{
var read = binreader.ReadUInt32();
if (read == fromActorID) //Original ID
{
binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin);
binWriter.Write(actorID);
}
}
}
}
}
}
public void DebugPrintPacket()
{
#if DEBUG
logger.ColorDebug(
string.Format("IsAuth:{0} IsEncrypted:{1}, Size:0x{2:X}, NumSubpackets:{3}{4}{5}",
header.isAuthenticated, header.isCompressed, header.packetSize, header.numSubpackets,
Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())), ConsoleOutputColor.DarkYellow);
foreach (var sub in GetSubpackets())
{
sub.DebugPrintSubPacket();
}
#endif
}
#region Utility Functions
public static BasePacket CreatePacket(List<SubPacket> subpackets, bool isAuthed, bool isCompressed)
{
//Create Header
var header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isCompressed = isCompressed ? (byte) 1 : (byte) 0;
header.numSubpackets = (ushort) subpackets.Count;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
foreach (var subpacket in subpackets)
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize - 0x10];
//Add Subpackets
var offset = 0;
foreach (var subpacket in subpackets)
{
var subpacketData = subpacket.GetBytes();
Array.Copy(subpacketData, 0, data, offset, subpacketData.Length);
offset += (ushort)subpacketData.Length;
}
//Compress this array into a new one if needed
if (isCompressed)
{
data = CompressData(data);
header.packetSize = (ushort)(BASEPACKET_SIZE + data.Length);
}
Debug.Assert(data != null && offset == data.Length && header.packetSize == 0x10 + offset);
var packet = new BasePacket(header, data);
return packet;
}
public static BasePacket CreatePacket(SubPacket subpacket, bool isAuthed, bool isCompressed)
{
//Create Header
var header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isCompressed = isCompressed ? (byte) 1 : (byte) 0;
header.numSubpackets = 1;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize - 0x10];
//Add Subpackets
byte[] subpacketData = subpacket.GetBytes();
//Compress this array into a new one if needed
if (isCompressed)
{
subpacketData = CompressData(subpacketData);
header.packetSize = (ushort)(BASEPACKET_SIZE + data.Length);
}
Array.Copy(subpacketData, 0, data, 0, subpacketData.Length);
Debug.Assert(data != null);
var packet = new BasePacket(header, data);
return packet;
}
public static BasePacket CreatePacket(byte[] data, bool isAuthed, bool isCompressed)
{
Debug.Assert(data != null);
//Create Header
var header = new BasePacketHeader();
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isCompressed = isCompressed ? (byte) 1 : (byte) 0;
header.numSubpackets = 1;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
header.packetSize += (ushort) data.Length;
//Compress this array into a new one if needed
if (isCompressed)
{
data = CompressData(data);
header.packetSize = (ushort)(BASEPACKET_SIZE + data.Length);
}
var packet = new BasePacket(header, data);
return packet;
}
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
public static BasePacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
{
BasePacket newPacket = null;
//Too small to even get length
if (bytesRead <= offset)
return null;
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
//Too small to whole packet
if (bytesRead < offset + packetSize)
return null;
if (buffer.Length < offset + packetSize)
return null;
try
{
newPacket = new BasePacket(buffer, ref offset);
}
catch (OverflowException)
{
return null;
}
return newPacket;
}
public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
{
var data = packet.data;
int size = packet.header.packetSize;
var offset = 0;
while (offset < data.Length)
{
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Encipher(data, offset + 0x10, header.subpacketSize - 0x10);
offset += header.subpacketSize;
}
}
public static unsafe void DecryptPacket(Blowfish blowfish, ref BasePacket packet)
{
var data = packet.data;
int size = packet.header.packetSize;
var offset = 0;
while (offset < data.Length)
{
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Decipher(data, offset + 0x10, header.subpacketSize - 0x10);
offset += header.subpacketSize;
}
}
public static unsafe void DecompressPacket(ref BasePacket packet)
{
using (var compressedStream = new MemoryStream(packet.data))
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
packet.data = resultStream.ToArray();
packet.header.isCompressed = 0;
packet.header.packetSize = (ushort)(BASEPACKET_SIZE + packet.data.Length);
}
}
public static unsafe BasePacket CompressPacket(BasePacket uncompressedPacket)
{
using (var compressedStream = new MemoryStream(uncompressedPacket.data))
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Compress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
BasePacket compressedPacket = BasePacket.CreatePacket(resultStream.ToArray(), uncompressedPacket.header.isAuthenticated == 1, true);
return compressedPacket;
}
}
public static unsafe byte[] CompressData(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Compress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
#endregion
}
public static class LoggerExtensions
{
public static void ColorDebug(this Logger logger, string message, ConsoleOutputColor color)
{
var logEvent = new LogEventInfo(LogLevel.Debug, logger.Name, message);
logEvent.Properties["color"] = (int) color;
logger.Log(logEvent);
}
}
}

View File

@@ -1,13 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
namespace FFXIVClassic_Lobby_Server.common
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
namespace Meteor.Common
{
[global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class BitfieldLengthAttribute : Attribute
public sealed class BitfieldLengthAttribute : Attribute
{
uint length;
@@ -19,7 +36,7 @@ namespace FFXIVClassic_Lobby_Server.common
public uint Length { get { return length; } }
}
static class PrimitiveConversion
public static class PrimitiveConversion
{
public static UInt32 ToUInt32<T>(T t) where T : struct
{
@@ -64,7 +81,7 @@ namespace FFXIVClassic_Lobby_Server.common
// Calculate a bitmask of the desired length
long mask = 0;
for (int i = 0; i < fieldLength; i++)
mask |= 1 << i;
mask |= 1L << i;
r |= ((UInt32)f.GetValue(t) & mask) << offset;
@@ -75,4 +92,4 @@ namespace FFXIVClassic_Lobby_Server.common
return r;
}
}
}
}

View File

@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Meteor.Common
{
public class Bitstream
{
private byte[] Data;
public Bitstream(uint numBits, bool setAllTrue = false)
{
Debug.Assert(numBits % 8 == 0);
Debug.Assert(numBits % 4 == 0);
Data = new byte[numBits / 8];
if (setAllTrue)
SetAll(true);
}
public Bitstream(bool[] boolArray)
{
Data = Utils.ConvertBoolArrayToBinaryStream(boolArray);
}
private Bitstream(byte[] byteArray)
{
Data = byteArray;
}
public void SetAll(bool to)
{
for (int i = 0; i < Data.Length; i += 4)
{
Data[i] = Data[i + 1] = Data[i + 2] = Data[i + 3] = (byte)(to ? 0xFF : 0x00);
}
}
public void SetTo(Bitstream result)
{
Debug.Assert(Data.Length == result.Data.Length);
for (int i = 0; i < result.Data.Length; i += 4)
{
Data[i] = result.Data[i];
Data[i + 1] = result.Data[i + 1];
Data[i + 2] = result.Data[i + 2];
Data[i + 3] = result.Data[i + 3];
}
}
public void SetTo(bool[] result)
{
Debug.Assert(Data.Length == result.Length / 8);
Data = Utils.ConvertBoolArrayToBinaryStream(result);
}
public bool Get(uint at)
{
return Get((int)at);
}
public bool Get(int at)
{
int bytePos = at / 8;
int bitPos = at % 8;
return (Data[bytePos] & (1 << bitPos)) != 0;
}
public void Set(uint at)
{
Set((int)at);
}
public void Set(int at)
{
int bytePos = at / 8;
int bitPos = at % 8;
Data[bytePos] |= (byte)(1 << bitPos);
}
public void Clear(uint at)
{
Clear((int)at);
}
public void Clear(int at)
{
int bytePos = at / 8;
int bitPos = at % 8;
Data[bytePos] &= (byte)~(1 << bitPos);
}
public void NOT()
{
for (int i = 0; i < Data.Length; i += 4)
{
Data[i] = (byte)~Data[i];
Data[i + 1] = (byte)~Data[i + 1];
Data[i + 2] = (byte)~Data[i + 2];
Data[i + 3] = (byte)~Data[i + 3];
}
}
public void OR(Bitstream other)
{
Debug.Assert(Data.Length == other.Data.Length);
for (int i = 0; i < Data.Length; i += 4)
{
Data[i] |= other.Data[i];
Data[i + 1] |= other.Data[i + 1];
Data[i + 2] |= other.Data[i + 2];
Data[i + 3] |= other.Data[i + 3];
}
}
public void AND(Bitstream other)
{
Debug.Assert(Data.Length == other.Data.Length);
for (int i = 0; i < Data.Length; i += 4)
{
Data[i] &= other.Data[i];
Data[i + 1] &= other.Data[i + 1];
Data[i + 2] &= other.Data[i + 2];
Data[i + 3] &= other.Data[i + 3];
}
}
public void XOR(Bitstream other)
{
Debug.Assert(Data.Length == other.Data.Length);
for (int i = 0; i < Data.Length; i += 4)
{
Data[i] ^= other.Data[i];
Data[i + 1] ^= other.Data[i + 1];
Data[i + 2] ^= other.Data[i + 2];
Data[i + 3] ^= other.Data[i + 3];
}
}
public Bitstream Copy()
{
byte[] copy = new byte[Data.Length];
Array.Copy(Data, copy, Data.Length);
return new Bitstream(copy);
}
public byte[] GetBytes()
{
return Data;
}
public byte[] GetSlice(ushort from, ushort to)
{
int remainder = ((to - from) % 8 != 0) ? 1 : 0;
byte[] toReturn = new byte[((to - from) / 8) + remainder + 1];
toReturn[toReturn.Length - 1] = 0x3;
byte curByte = 0;
int destByteIndx = 0;
int destShiftIndx = 0;
int srcByteIndx = from / 8;
int srcShiftIndx = from % 8;
for (int i = from; i <= to; i++)
{
// Skip Zeros
if (Data[srcByteIndx] == 0)
{
srcByteIndx++;
srcShiftIndx = 0;
destByteIndx++;
i += 8;
continue;
}
bool val = (Data[srcByteIndx] & (1 << srcShiftIndx++)) != 0;
curByte |= (byte)((val ? 1 : 0) << destShiftIndx++);
if (srcShiftIndx == 8)
{
srcShiftIndx = 0;
srcByteIndx++;
}
if (destShiftIndx == 8)
{
toReturn[destByteIndx++] = curByte;
destShiftIndx = 0;
curByte = 0;
}
}
if (destByteIndx == toReturn.Length - 2)
toReturn[destByteIndx] = curByte;
return toReturn;
}
}
}

View File

@@ -1,10 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
namespace FFXIVClassic_Lobby_Server.common
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
namespace Meteor.Common
{
public class Blowfish
{
@@ -287,7 +304,7 @@ namespace FFXIVClassic_Lobby_Server.common
public Blowfish(byte[] key)
{
initializeBlowfish(key);
InitializeBlowfish(key);
}
public void Encipher(byte[] data, int offset, int length)
@@ -299,7 +316,7 @@ namespace FFXIVClassic_Lobby_Server.common
{
uint xl = (uint)((data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24));
uint xr = (uint)((data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24));
blowfish_encipher(ref xl, ref xr);
BlowfishEncipher(ref xl, ref xr);
data[i + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16);
@@ -320,7 +337,7 @@ namespace FFXIVClassic_Lobby_Server.common
{
uint xl = (uint)((data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24));
uint xr = (uint)((data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24));
blowfish_decipher(ref xl, ref xr);
BlowfishDecipher(ref xl, ref xr);
data[i + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16);
@@ -355,7 +372,7 @@ namespace FFXIVClassic_Lobby_Server.common
return y;
}
private void blowfish_encipher(ref UInt32 xl, ref UInt32 xr)
private void BlowfishEncipher(ref UInt32 xl, ref UInt32 xr)
{
UInt32 temp;
Int32 i;
@@ -378,7 +395,7 @@ namespace FFXIVClassic_Lobby_Server.common
}
private void blowfish_decipher(ref UInt32 xl, ref UInt32 xr)
private void BlowfishDecipher(ref UInt32 xl, ref UInt32 xr)
{
UInt32 temp;
Int32 i;
@@ -387,13 +404,13 @@ namespace FFXIVClassic_Lobby_Server.common
xl = xl ^ P[i];
xr = F(xl) ^ xr;
/* Exchange xl and xr */
/* ExChange xl and xr */
temp = xl;
xl = xr;
xr = temp;
}
/* Exchange xl and xr */
/* ExChange xl and xr */
temp = xl;
xl = xr;
xr = temp;
@@ -403,7 +420,7 @@ namespace FFXIVClassic_Lobby_Server.common
}
private int initializeBlowfish(byte [] key)
private int InitializeBlowfish(byte [] key)
{
Int16 i;
Int16 j;
@@ -437,7 +454,7 @@ namespace FFXIVClassic_Lobby_Server.common
for (i = 0; i < N + 2; i += 2)
{
blowfish_encipher(ref datal, ref datar);
BlowfishEncipher(ref datal, ref datar);
P[i] = datal;
P[i + 1] = datar;
@@ -447,7 +464,7 @@ namespace FFXIVClassic_Lobby_Server.common
{
for (j = 0; j < 256; j += 2)
{
blowfish_encipher(ref datal, ref datar);
BlowfishEncipher(ref datal, ref datar);
S[i,j] = datal;
S[i,j + 1] = datar;
}

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props') AND '$(OS)' == 'Windows_NT'" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props') AND '$(OS)' == 'Windows_NT'" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3A3D6626-C820-4C18-8C81-64811424F20E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Meteor.Common</RootNamespace>
<AssemblyName>Meteor.Common</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<NuGetPackageImportStamp>792e4711</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<RegisterForComInterop>false</RegisterForComInterop>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="DotNetZip">
<HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.5.0\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BasePacket.cs" />
<Compile Include="Bitfield.cs" />
<Compile Include="Bitstream.cs" />
<Compile Include="Blowfish.cs" />
<Compile Include="EfficientHashTables.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sql.cs" />
<Compile Include="STA_INIFile.cs" />
<Compile Include="SubPacket.cs" />
<Compile Include="Utils.cs" />
<Compile Include="Vector3.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,179 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
namespace Meteor.Common
{
namespace EfficientHashTables
{
public class Efficient64bitHashTable<T>
{
private class element
{
public ulong _key;
public T _value;
};
private element[][] _buckets;
private uint _capacity;
public Efficient64bitHashTable()
{
_capacity = 214373; // some prime number
_buckets = new element[_capacity][];
}
public Efficient64bitHashTable(uint capacity)
{
_capacity = capacity;
_buckets = new element[_capacity][];
}
public uint Hash(ulong key)
{
return (uint)(key % _capacity);
}
public void Add(ulong key, T value)
{
uint hsh = Hash(key);
element[] e;
if (_buckets[hsh] == null)
_buckets[hsh] = e = new element[1];
else
{
foreach (var elem in _buckets[hsh])
if (elem._key == key)
{
elem._value = value;
return;
}
e = new element[_buckets[hsh].Length + 1];
Array.Copy(_buckets[hsh], 0, e, 1, _buckets[hsh].Length);
_buckets[hsh] = e;
}
e[0] = new element { _key = key, _value = value };
}
public T Get(ulong key)
{
uint hsh = Hash(key);
element[] e = _buckets[hsh];
if (e == null) return default(T);
foreach (var f in e)
if (f._key == key)
return f._value;
return default(T);
}
public bool Has(ulong key)
{
uint hsh = Hash(key);
element[] e = _buckets[hsh];
if (e == null) return false;
foreach (var f in e)
if (f._key == key)
return true;
return false;
}
public int Count()
{
int r = 0;
foreach (var e in _buckets)
if (e != null)
r += e.Length;
return r;
}
}
public class Efficient32bitHashTable<T>
{
private class element
{
public uint _key;
public T _value;
};
private element[][] _buckets;
private uint _capacity;
public Efficient32bitHashTable()
{
_capacity = 463; // some prime number
_buckets = new element[_capacity][];
}
public Efficient32bitHashTable(uint capacity)
{
_capacity = capacity;
_buckets = new element[_capacity][];
}
public uint Hash(uint key)
{
return (uint)(key % _capacity);
}
public void Add(uint key, T value)
{
uint hsh = Hash(key);
element[] e;
if (_buckets[hsh] == null)
_buckets[hsh] = e = new element[1];
else
{
foreach (var elem in _buckets[hsh])
if (elem._key == key)
{
elem._value = value;
return;
}
e = new element[_buckets[hsh].Length + 1];
Array.Copy(_buckets[hsh], 0, e, 1, _buckets[hsh].Length);
_buckets[hsh] = e;
}
e[0] = new element { _key = key, _value = value };
}
public T Get(uint key)
{
uint hsh = Hash(key);
element[] e = _buckets[hsh];
if (e == null) return default(T);
foreach (var f in e)
if (f._key == key)
return f._value;
return default(T);
}
public int Count()
{
int r = 0;
foreach (var e in _buckets)
if (e != null)
r += e.Length;
return r;
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("FFXIVClassic.Common")]
[assembly: AssemblyDescription("Common class library for FFXIVClassic project")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ffxivclassic.fragmenterworks.com")]
[assembly: AssemblyProduct("FFXIVClassic.Common")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3a3d6626-c820-4c18-8c81-64811424f20e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -3,16 +3,16 @@
// *******************************
// *** (C)2009-2013 S.T.A. snc ***
// *******************************
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace STA.Settings
namespace Meteor.Common
{
internal class INIFile
public class INIFile
{
#region "Declarations"
@@ -179,7 +179,7 @@ namespace STA.Settings
// *** Check if original file exists ***
bool OriginalFileExists = File.Exists(m_FileName);
// *** Get temporary file name ***
// *** get temporary file name ***
string TmpFileName = Path.ChangeExtension(m_FileName, "$n$");
// *** Copy content of original file to temporary file, replace modified values ***
@@ -199,7 +199,7 @@ namespace STA.Settings
// *** Open the original file ***
sr = new StreamReader(m_FileName);
// *** Read the file original content, replace changes with local cache values ***
// *** Read the file original content, replace Changes with local cache values ***
string s;
string SectionName;
string Key = null;
@@ -337,7 +337,7 @@ namespace STA.Settings
}
// *** Read a value from local cache ***
internal string GetValue(string SectionName, string Key, string DefaultValue)
public string GetValue(string SectionName, string Key, string DefaultValue)
{
// *** Lazy loading ***
if (m_Lazy)
@@ -380,7 +380,7 @@ namespace STA.Settings
Dictionary<string, string> Section;
if (!m_Sections.TryGetValue(SectionName, out Section))
{
// *** If it doesn't, add it ***
// *** If it Doesn't, Add it ***
Section = new Dictionary<string, string>();
m_Sections.Add(SectionName,Section);
}
@@ -474,7 +474,7 @@ namespace STA.Settings
return DefaultValue;
}
internal double GetValue(string SectionName, string Key, double DefaultValue)
internal Double GetValue(string SectionName, string Key, Double DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
double Value;
@@ -519,7 +519,7 @@ namespace STA.Settings
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}
internal void SetValue(string SectionName, string Key, double Value)
internal void SetValue(string SectionName, string Key, Double Value)
{
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}

33
Common Class Lib/Sql.cs Normal file
View File

@@ -0,0 +1,33 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using NLog;
namespace Meteor.Common
{
// todo:
// havent decided whether it's worth wrapping every sql class
// so i'll just leave it with logger for now
public class Sql
{
public static Logger Log = LogManager.GetCurrentClassLogger();
}
}

View File

@@ -0,0 +1,239 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
using System.Runtime.InteropServices;
using NLog;
using NLog.Targets;
namespace Meteor.Common
{
[StructLayout(LayoutKind.Sequential)]
public struct SubPacketHeader
{
public ushort subpacketSize;
public ushort type;
public uint sourceId;
public uint targetId;
public uint unknown1;
}
[StructLayout(LayoutKind.Sequential)]
public struct GameMessageHeader
{
public ushort unknown4; //Always 0x14
public ushort opcode;
public uint unknown5;
public uint timestamp;
public uint unknown6;
}
public class SubPacket
{
public const int SUBPACKET_SIZE = 0x10;
public const int GAMEMESSAGE_SIZE = 0x10;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public byte[] data;
public GameMessageHeader gameMessage;
public SubPacketHeader header;
public unsafe SubPacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (header.type == 0x3)
{
fixed (byte* pdata = &bytes[offset + SUBPACKET_SIZE])
{
gameMessage =
(GameMessageHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(GameMessageHeader));
}
}
if (bytes.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
if (header.type == 0x3)
{
data = new byte[header.subpacketSize - SUBPACKET_SIZE - GAMEMESSAGE_SIZE];
Array.Copy(bytes, offset + SUBPACKET_SIZE + GAMEMESSAGE_SIZE, data, 0, data.Length);
}
else
{
data = new byte[header.subpacketSize - SUBPACKET_SIZE];
Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length);
}
offset += header.subpacketSize;
}
public SubPacket(ushort opcode, uint sourceId, byte[] data) : this(true, opcode, sourceId, data) { }
public SubPacket(bool isGameMessage, ushort opcode, uint sourceId, byte[] data)
{
header = new SubPacketHeader();
if (isGameMessage)
{
gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode;
gameMessage.timestamp = Utils.UnixTimeStampUTC();
gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 0x00;
}
header.sourceId = sourceId;
header.targetId = 0;
if (isGameMessage)
header.type = 0x03;
else
header.type = opcode;
header.unknown1 = 0x00;
this.data = data;
header.subpacketSize = (ushort) (SUBPACKET_SIZE + data.Length);
if (isGameMessage)
header.subpacketSize += GAMEMESSAGE_SIZE;
}
public SubPacket(SubPacket original, uint newTargetId)
{
header = new SubPacketHeader();
gameMessage = original.gameMessage;
header.subpacketSize = original.header.subpacketSize;
header.type = original.header.type;
header.sourceId = original.header.sourceId;
header.targetId = newTargetId;
data = original.data;
}
public void SetTargetId(uint target)
{
this.header.targetId = target;
}
public byte[] GetHeaderBytes()
{
var size = Marshal.SizeOf(header);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetGameMessageBytes()
{
var size = Marshal.SizeOf(gameMessage);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(gameMessage, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetBytes()
{
var outBytes = new byte[header.subpacketSize];
Array.Copy(GetHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE);
if (header.type == 0x3)
Array.Copy(GetGameMessageBytes(), 0, outBytes, SUBPACKET_SIZE, GAMEMESSAGE_SIZE);
Array.Copy(data, 0, outBytes, SUBPACKET_SIZE + (header.type == 0x3 ? GAMEMESSAGE_SIZE : 0), data.Length);
return outBytes;
}
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
public static SubPacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
{
SubPacket newPacket = null;
//Too small to even get length
if (bytesRead <= offset)
return null;
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
//Too small to whole packet
if (bytesRead < offset + packetSize)
return null;
if (buffer.Length < offset + packetSize)
return null;
try
{
newPacket = new SubPacket(buffer, ref offset);
}
catch (OverflowException)
{
return null;
}
return newPacket;
}
public void DebugPrintSubPacket()
{
#if DEBUG
logger.ColorDebug(
string.Format("Size:0x{0:X} Opcode:0x{1:X}{2}{3}", header.subpacketSize, gameMessage.opcode,
Environment.NewLine,
Utils.ByteArrayToHex(GetHeaderBytes())), ConsoleOutputColor.DarkRed);
if (header.type == 0x03)
{
logger.ColorDebug(Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE),
ConsoleOutputColor.DarkRed);
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
ConsoleOutputColor.DarkMagenta);
}
else
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE),
ConsoleOutputColor.DarkMagenta);
#endif
}
}
}

520
Common Class Lib/Utils.cs Normal file
View File

@@ -0,0 +1,520 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
using System.IO;
using System.Text;
namespace Meteor.Common
{
public static class Utils
{
private static readonly uint[] _lookup32 = CreateLookup32();
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static uint[] CreateLookup32()
{
var result = new uint[256];
for (var i = 0; i < 256; i++)
{
var s = i.ToString("X2");
result[i] = s[0] + ((uint)s[1] << 16);
}
return result;
}
public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16)
{
if (bytes == null)
{
return string.Empty;
}
var hexChars = "0123456789ABCDEF".ToCharArray();
var offsetBlock = 8 + 3;
var byteBlock = offsetBlock + bytesPerLine * 3 + (bytesPerLine - 1) / 8 + 2;
var lineLength = byteBlock + bytesPerLine + Environment.NewLine.Length;
var line = (new string(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray();
var numLines = (bytes.Length + bytesPerLine - 1) / bytesPerLine;
var sb = new StringBuilder(numLines * lineLength);
for (var i = 0; i < bytes.Length; i += bytesPerLine)
{
var h = i + offset;
line[0] = hexChars[(h >> 28) & 0xF];
line[1] = hexChars[(h >> 24) & 0xF];
line[2] = hexChars[(h >> 20) & 0xF];
line[3] = hexChars[(h >> 16) & 0xF];
line[4] = hexChars[(h >> 12) & 0xF];
line[5] = hexChars[(h >> 8) & 0xF];
line[6] = hexChars[(h >> 4) & 0xF];
line[7] = hexChars[(h >> 0) & 0xF];
var hexColumn = offsetBlock;
var charColumn = byteBlock;
for (var j = 0; j < bytesPerLine; j++)
{
if (j > 0 && (j & 7) == 0)
{
hexColumn++;
}
if (i + j >= bytes.Length)
{
line[hexColumn] = ' ';
line[hexColumn + 1] = ' ';
line[charColumn] = ' ';
}
else
{
var by = bytes[i + j];
line[hexColumn] = hexChars[(by >> 4) & 0xF];
line[hexColumn + 1] = hexChars[by & 0xF];
line[charColumn] = by < 32 ? '.' : (char)by;
}
hexColumn += 3;
charColumn++;
}
sb.Append(line);
}
return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray());
}
public static uint UnixTimeStampUTC(DateTime? time = null)
{
uint unixTimeStamp;
var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (uint)zuluTime.Subtract(unixEpoch).TotalSeconds;
return unixTimeStamp;
}
public static ulong MilisUnixTimeStampUTC(DateTime? time = null)
{
ulong unixTimeStamp;
var currentTime = time ?? DateTime.Now;
var zuluTime = currentTime.ToUniversalTime();
var unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (ulong)zuluTime.Subtract(unixEpoch).TotalMilliseconds;
return unixTimeStamp;
}
public static DateTime UnixTimeStampToDateTime(uint timestamp)
{
return epoch.AddSeconds(timestamp);
}
public static ulong SwapEndian(ulong input)
{
return 0x00000000000000FF & (input >> 56) |
0x000000000000FF00 & (input >> 40) |
0x0000000000FF0000 & (input >> 24) |
0x00000000FF000000 & (input >> 8) |
0x000000FF00000000 & (input << 8) |
0x0000FF0000000000 & (input << 24) |
0x00FF000000000000 & (input << 40) |
0xFF00000000000000 & (input << 56);
}
public static uint SwapEndian(uint input)
{
return ((input >> 24) & 0xff) |
((input << 8) & 0xff0000) |
((input >> 8) & 0xff00) |
((input << 24) & 0xff000000);
}
public static int SwapEndian(int input)
{
var inputAsUint = (uint)input;
input = (int)
(((inputAsUint >> 24) & 0xff) |
((inputAsUint << 8) & 0xff0000) |
((inputAsUint >> 8) & 0xff00) |
((inputAsUint << 24) & 0xff000000));
return input;
}
public static ushort SwapEndian(ushort input)
{
return (ushort)(((input << 8) & 0xff00) |
((input >> 8) & 0x00ff));
}
public static uint MurmurHash2(string key, uint seed)
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
var data = Encoding.ASCII.GetBytes(key);
const uint m = 0x5bd1e995;
const int r = 24;
var len = key.Length;
var dataIndex = len - 4;
// Initialize the hash to a 'random' value
var h = seed ^ (uint)len;
// Mix 4 bytes at a time into the hash
while (len >= 4)
{
h *= m;
var k = (uint)BitConverter.ToInt32(data, dataIndex);
k = ((k >> 24) & 0xff) | // move byte 3 to byte 0
((k << 8) & 0xff0000) | // move byte 1 to byte 2
((k >> 8) & 0xff00) | // move byte 2 to byte 1
((k << 24) & 0xff000000); // byte 0 to byte 3
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
dataIndex -= 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch (len)
{
case 3:
h ^= (uint)data[0] << 16;
goto case 2;
case 2:
h ^= (uint)data[len - 2] << 8;
goto case 1;
case 1:
h ^= data[len - 1];
h *= m;
break;
}
;
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
public static byte[] ConvertBoolArrayToBinaryStream(bool[] array)
{
var data = new byte[array.Length / 8 + (array.Length % 8 != 0 ? 1 : 0)];
var dataCounter = 0;
for (var i = 0; i < array.Length; i += 8)
{
for (var bitCount = 0; bitCount < 8; bitCount++)
{
if (i + bitCount >= array.Length - 1)
break;
data[dataCounter] = (byte)(((array[i + bitCount] ? 1 : 0) << 7 - bitCount) | data[dataCounter]);
}
dataCounter++;
}
return data;
}
public static bool[] ConvertBinaryStreamToBoolArray(byte[] bytes)
{
bool[] data = new bool[bytes.Length * 8];
int boolCounter = 0;
for (int i = 0; i < bytes.Length; i ++)
{
if (bytes[i] == 0)
{
boolCounter += 8;
continue;
}
for (int bitCount = 0; bitCount < 8; bitCount++)
data[boolCounter++] = (bytes[i] >> bitCount & 1) == 1;
}
return data;
}
public static string ToStringBase63(int number)
{
var lookup = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var secondDigit = lookup.Substring((int)Math.Floor(number / (double)lookup.Length), 1);
var firstDigit = lookup.Substring(number % lookup.Length, 1);
return secondDigit + firstDigit;
}
public static string ReadNullTermString(BinaryReader reader, int maxSize = 0x20)
{
long pos = reader.BaseStream.Position;
int size = 0;
for (int i = 0; i < maxSize; i++)
{
if (reader.ReadByte() == 0)
{
size = i;
break;
}
}
reader.BaseStream.Seek(pos, SeekOrigin.Begin);
string result = Encoding.ASCII.GetString(reader.ReadBytes(size));
reader.BaseStream.Seek(pos + maxSize, SeekOrigin.Begin);
return result;
}
public static void WriteNullTermString(BinaryWriter writer, string value, int maxSize = 0x20)
{
writer.Write(Encoding.ASCII.GetBytes(value), 0, Encoding.ASCII.GetByteCount(value) >= maxSize ? maxSize : Encoding.ASCII.GetByteCount(value));
}
public static string FFXIVLoginStringDecodeBinary(string path)
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
byte[] data = File.ReadAllBytes(path);
int offset = 0x5405a;
//int offset = 0x5425d;
//int offset = 0x53ea0;
while (true)
{
string result = "";
uint key = (uint)data[offset + 0] << 8 | data[offset + 1];
uint key2 = data[offset + 2];
key = RotateRight(key, 1) & 0xFFFF;
key -= 0x22AF;
key &= 0xFFFF;
key2 = key2 ^ key;
key = RotateRight(key, 1) & 0xFFFF;
key -= 0x22AF;
key &= 0xFFFF;
uint finalKey = key;
key = data[offset + 3];
uint count = (key2 & 0xFF) << 8;
key = key ^ finalKey;
key &= 0xFF;
count |= key;
int count2 = 0;
while (count != 0)
{
uint encrypted = data[offset + 4 + count2];
finalKey = RotateRight(finalKey, 1) & 0xFFFF;
finalKey -= 0x22AF;
finalKey &= 0xFFFF;
encrypted = encrypted ^ (finalKey & 0xFF);
result += (char)encrypted;
count--;
count2++;
}
offset += 4 + count2;
}
}
public static string FFXIVLoginStringDecode(byte[] data)
{
string result = "";
uint key = (uint)data[0] << 8 | data[1];
uint key2 = data[2];
key = RotateRight(key, 1) & 0xFFFF;
key -= 0x22AF;
key2 = key2 ^ key;
key = RotateRight(key, 1) & 0xFFFF;
key -= 0x22AF;
uint finalKey = key;
key = data[3];
uint count = (key2 & 0xFF) << 8;
key = key ^ finalKey;
key &= 0xFF;
count |= key;
int count2 = 0;
while (count != 0)
{
uint encrypted = data[4 + count2];
finalKey = RotateRight(finalKey, 1) & 0xFFFF;
finalKey -= 0x22AF;
encrypted = encrypted ^ (finalKey & 0xFF);
result += (char)encrypted;
count--;
count2++;
}
return result;
}
public static byte[] FFXIVLoginStringEncode(uint key, string text)
{
key = key & 0xFFFF;
uint count = 0;
byte[] asciiBytes = Encoding.ASCII.GetBytes(text);
byte[] result = new byte[4 + text.Length];
for (count = 0; count < text.Length; count++)
{
result[result.Length - count - 1] = (byte)(asciiBytes[asciiBytes.Length - count - 1] ^ (key & 0xFF));
key += 0x22AF;
key &= 0xFFFF;
key = RotateLeft(key, 1) & 0xFFFF;
}
count = count ^ key;
result[3] = (byte)(count & 0xFF);
key += 0x22AF & 0xFFFF;
key = RotateLeft(key, 1) & 0xFFFF;
result[2] = (byte)(key & 0xFF);
key += 0x22AF & 0xFFFF;
key = RotateLeft(key, 1) & 0xFFFF;
result[1] = (byte)(key & 0xFF);
result[0] = (byte)((key >> 8) & 0xFF);
return result;
}
public static uint RotateLeft(uint value, int bits)
{
return (value << bits) | (value >> (16 - bits));
}
public static uint RotateRight(uint value, int bits)
{
return (value >> bits) | (value << (16 - bits));
}
public static T Clamp<T>(this T value, T min, T max) where T : IComparable<T>
{
if (value.CompareTo(min) < 0)
return min;
else if (value.CompareTo(max) > 0)
return max;
else
return value;
}
public static T Min<T>(this T value, T min) where T : IComparable<T>
{
if (value.CompareTo(min) > 0)
return min;
else
return value;
}
public static T Max<T>(this T value, T max) where T : IComparable<T>
{
if (value.CompareTo(max) < 0)
return max;
else
return value;
}
public static float DistanceSquared(Vector3 lhs, Vector3 rhs)
{
return DistanceSquared(lhs.X, lhs.Y, lhs.Z, rhs.X, rhs.Y, rhs.Z);
}
public static float Distance(Vector3 lhs, Vector3 rhs)
{
return Distance(lhs.X, lhs.Y, lhs.Z, rhs.X, rhs.Y, rhs.Z);
}
public static float Distance(float x, float y, float z, float x2, float y2, float z2)
{
if (x == x2 && y == y2 && z == z2)
return 0.0f;
return (float)Math.Sqrt(DistanceSquared(x, y, z, x2, y2, z2));
}
public static float DistanceSquared(float x, float y, float z, float x2, float y2, float z2)
{
if (x == x2 && y == y2 && z == z2)
return 0.0f;
// todo: my maths is shit
var dx = x - x2;
var dy = y - y2;
var dz = z - z2;
return dx * dx + dy * dy + dz * dz;
}
//Distance of just the x and z valeus, ignoring y
public static float XZDistanceSquared(Vector3 lhs, Vector3 rhs)
{
return XZDistanceSquared(lhs.X, lhs.Z, rhs.X, rhs.Z);
}
public static float XZDistance(Vector3 lhs, Vector3 rhs)
{
return XZDistance(lhs.X, lhs.Z, rhs.X, rhs.Z);
}
public static float XZDistance(float x, float z, float x2, float z2)
{
if (x == x2 && z == z2)
return 0.0f;
return (float)Math.Sqrt(XZDistanceSquared(x, z, x2, z2));
}
public static float XZDistanceSquared(float x, float z, float x2, float z2)
{
if (x == x2 && z == z2)
return 0.0f;
// todo: mz maths is shit
var dx = x - x2;
var dz = z - z2;
return dx * dx + dz * dz;
}
}
}

180
Common Class Lib/Vector3.cs Normal file
View File

@@ -0,0 +1,180 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
namespace Meteor.Common
{
public class Vector3
{
public float X;
public float Y;
public float Z;
public static Vector3 Zero = new Vector3();
public Vector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public Vector3()
{
X = 0.0f;
Y = 0.0f;
Z = 0.0f;
}
public static Vector3 operator +(Vector3 lhs, Vector3 rhs)
{
Vector3 newVec = new Vector3(lhs.X, lhs.Y, lhs.Z);
newVec.X += rhs.X;
newVec.Y += rhs.Y;
newVec.Z += rhs.Z;
return newVec;
}
public static Vector3 operator -(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.X - rhs.X, lhs.Y - rhs.Y, lhs.Z - rhs.Z);
}
public static Vector3 operator *(Vector3 lhs, Vector3 rhs)
{
return new Vector3(lhs.X * rhs.X, lhs.Y * rhs.Y, lhs.Z * rhs.Z);
}
public static Vector3 operator *(float scalar, Vector3 rhs)
{
return new Vector3(scalar * rhs.X, scalar * rhs.Y, scalar * rhs.Z);
}
public static Vector3 operator /(Vector3 lhs, float scalar)
{
return new Vector3(lhs.X / scalar, lhs.Y / scalar, lhs.Z / scalar);
}
public static bool operator !=(Vector3 lhs, Vector3 rhs)
{
return !(lhs?.X == rhs?.X && lhs?.Y == rhs?.Y && lhs?.Z == rhs?.Z);
}
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
return (lhs?.X == rhs?.X && lhs?.Y == rhs?.Y && lhs?.Z == rhs?.Z);
}
public float Length()
{
return (float)Math.Sqrt(this.LengthSquared());
}
public float LengthSquared()
{
return (this.X * this.X) + (this.Y * this.Y) + (this.Z * this.Z);
}
public static float Dot(Vector3 lhs, Vector3 rhs)
{
return (lhs.X * rhs.X) + (lhs.Y * rhs.Y) + (lhs.Z * rhs.Z);
}
public static float GetAngle(Vector3 lhs, Vector3 rhs)
{
return GetAngle(lhs.X, lhs.Z, rhs.X, rhs.Z);
}
public static float GetAngle(float x, float z, float x2, float z2)
{
if (x == x2)
return 0.0f;
var angle = (float)(Math.Atan((z2 - z) / (x2 - x)));
return (float)(x > x2 ? angle + Math.PI : angle);
}
public Vector3 NewHorizontalVector(float angle, float extents)
{
var newVec = new Vector3();
newVec.Y = this.Y;
newVec.X = this.X + (float)Math.Cos(angle) * extents;
newVec.Z = this.Z + (float)Math.Sin(angle) * extents;
return newVec;
}
public bool IsWithinCircle(Vector3 center, float maxRadius, float minRadius)
{
if (this.X == center.X && this.Z == center.Z)
return true;
float diffX = center.X - this.X;
float diffZ = center.Z - this.Z;
float distance = Utils.XZDistance(center.X, center.Z, X, Z);
return distance <= maxRadius && distance >= minRadius;
}
public bool IsWithinBox(Vector3 upperLeftCorner, Vector3 lowerRightCorner)
{
return upperLeftCorner.X <= this.X &&
upperLeftCorner.Y <= this.Y &&
upperLeftCorner.Z <= this.Z &&
lowerRightCorner.X >= this.X &&
lowerRightCorner.Y >= this.Y &&
lowerRightCorner.Z >= this.Z;
}
//Checks if this vector is in a cone, note it doesn't check for distance
public bool IsWithinCone(Vector3 coneCenter, float coneRotation, float coneAngle)
{
float angleToTarget = GetAngle(coneCenter, this);
float halfAngleOfAoe = (float) (coneAngle * Math.PI / 2);
float rotationToAdd = coneRotation + halfAngleOfAoe;
//This is the angle relative to the lower angle of the cone
angleToTarget = (angleToTarget + rotationToAdd - (0.5f * (float)Math.PI)) % (2 * (float) Math.PI);
//If the relative angle is less than the total angle of the cone, the target is inside the cone
return angleToTarget >= 0 && angleToTarget <= (coneAngle * Math.PI);
}
public override bool Equals(object obj)
{
var vector = obj as Vector3;
return vector != null &&
X == vector.X &&
Y == vector.Y &&
Z == vector.Z;
}
public override int GetHashCode()
{
var hashCode = -307843816;
hashCode = hashCode * -1521134295 + X.GetHashCode();
hashCode = hashCode * -1521134295 + Y.GetHashCode();
hashCode = hashCode * -1521134295 + Z.GetHashCode();
return hashCode;
}
}
}

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
<remove invariant="MySql.Data.MySqlClient"/>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</DbProviderFactories>
</system.data>
</configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DotNetZip" version="1.10.1" targetFramework="net45" />
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
<package id="NLog" version="4.5.0" targetFramework="net451" />
</packages>

11
Data/lobby_config.ini Normal file
View File

@@ -0,0 +1,11 @@
[General]
server_ip=0.0.0.0
showtimestamp = true
[Database]
worldid=1
host=127.0.0.1
port=3306
database=ffxiv_server
username=root
password=

11
Data/map_config.ini Normal file
View File

@@ -0,0 +1,11 @@
[General]
server_ip=127.0.0.1
showtimestamp = true
[Database]
worldid=1
host=127.0.0.1
port=3306
database=ffxiv_server
username=root
password=

58
Data/scripts/ability.lua Normal file
View File

@@ -0,0 +1,58 @@
-- todo: add enums for status effects in global.lua
require("global")
require("battleutils")
--[[
statId - see BattleTemp.cs
modifier - Modifier.Intelligence, Modifier.Mind (see Modifier.cs)
multiplier -
]]
function HandleHealingSkill(caster, target, skill, action, statId, modifierId, multiplier, baseAmount)
potency = potency or 1.0;
healAmount = baseAmount;
-- todo: shit based on mnd
local mind = caster.GetMod(Modifier.Mind);
end;
function HandleAttackSkill(caster, target, skill, action, statId, modifierId, multiplier, baseAmount)
-- todo: actually handle this
damage = baseAmount or math.random(1,10) * 10;
return damage;
end;
function HandleStoneskin(caster, target, skill, action, statId, modifierId, damage)
--[[
if target.statusEffects.HasStatusEffect(StatusEffect.Stoneskin) then
-- todo: damage reduction
return true;
end;
]]
return false;
end;
--For abilities that inflict statuses, like aegis boon or taunt
function onStatusAbilityFinish(caster, target, skill, action)
--action.CalcHitType(caster, target, skill);
action.DoAction(caster, target, skill);
action.TryStatus(caster, target, skill, false);
return action.amount;
end;
function onAttackAbilityFinish(caster, target, skill, action)
local damage = math.random(50, 150);
action.amount = damage;
action.DoAction(caster, target, skill);
return action.amount;
end;
function onHealAbilityFinish(caster, target, skill, action)
local amount = math.random(150, 250);
action.amount = amount;
action.DoAction(caster, target, skill);
action.TryStatus(caster, target, skill, true);
return action.amount;
end;

205
Data/scripts/aetheryte.lua Normal file
View File

@@ -0,0 +1,205 @@
--[[
Aetheryte related info
--]]
aetheryteParentLinks = {
--La Noscea
[1280001] = nil,
[1280002] = {1280007, 1280008, 1280009, 0, 0},
[1280003] = {1280010, 0, 0, 0, 0},
[1280004] = {1280011, 1280018, 0, 0, 0},
[1280005] = {1280020, 1280012, 1280013, 1280014, 0},
[1280006] = {1280015, 1280016, 1280017, 0, 0},
--Thanalan
[1280031] = nil,
[1280032] = {1280037, 1280038, 1280052, 0, 0},
[1280033] = {1280039, 1280040, 1280041, 0, 0},
[1280034] = {1280042, 1280043, 1280044, 1280054, 0},
[1280035] = {1280045, 1280046, 1280047, 0, 0},
[1280036] = {1280048, 1280049, 1280050, 0, 0},
--Black Shroud
[1280061] = nil,
[1280062] = {1280067, 1280068, 1280069, 1280083, 0},
[1280063] = {1280070, 1280071, 1280072, 0, 0},
[1280064] = {1280073, 1280074, 1280075, 1280082, 0},
[1280065] = {1280076, 1280077, 1280078, 0, 0},
[1280066] = {1280079, 1280080, 1280081, 0, 0},
--Coerthas
[1280092] = {1280097, 1280098, 1280099, 0, 0},
[1280093] = {1280100, 1280101, 1280102, 0, 0},
[1280094] = {1280103, 1280104, 0, 0, 0},
[1280095] = {1280105, 1280106, 1280107, 0, 0},
[1280096] = {1280108, 1280109, 1280110, 0, 0},
--Mor Dhona
[1280121] = {1280124, 1280125, 0, 0, 0},
[1280122] = {1280123, 0, 0, 0, 0}
}
aetheryteChildLinks = {
--La Noscea
[1280007] = 1280002,
[1280008] = 1280002,
[1280009] = 1280002,
[1280010] = 1280003,
[1280011] = 1280004,
[1280012] = 1280005,
[1280013] = 1280005,
[1280014] = 1280005,
[1280015] = 1280006,
[1280016] = 1280006,
[1280017] = 1280006,
[1280018] = 1280004,
[1280020] = 1280005,
--Thanalan
[1280037] = 1280032,
[1280038] = 1280032,
[1280039] = 1280033,
[1280040] = 1280033,
[1280041] = 1280033,
[1280042] = 1280034,
[1280043] = 1280034,
[1280044] = 1280034,
[1280045] = 1280035,
[1280046] = 1280035,
[1280047] = 1280035,
[1280048] = 1280036,
[1280049] = 1280036,
[1280050] = 1280036,
[1280052] = 1280032,
[1280054] = 1280034,
--Black Shroud
[1280067] = 1280062,
[1280068] = 1280062,
[1280069] = 1280062,
[1280070] = 1280063,
[1280071] = 1280063,
[1280072] = 1280063,
[1280073] = 1280064,
[1280074] = 1280064,
[1280075] = 1280064,
[1280076] = 1280065,
[1280077] = 1280065,
[1280078] = 1280065,
[1280079] = 1280066,
[1280080] = 1280066,
[1280081] = 1280066,
[1280082] = 1280064,
[1280083] = 1280062,
--Coerthas
[1280097] = 1280092,
[1280098] = 1280092,
[1280099] = 1280092,
[1280100] = 1280093,
[1280101] = 1280093,
[1280102] = 1280093,
[1280103] = 1280094,
[1280104] = 1280094,
[1280105] = 1280095,
[1280106] = 1280095,
[1280107] = 1280095,
[1280108] = 1280096,
[1280109] = 1280096,
[1280110] = 1280096,
--Mor Dhona
[1280123] = 1280122,
[1280124] = 1280121,
[1280125] = 1280121
}
aetheryteTeleportPositions = {
--La Noscea
[1280001] = {230, -407, 42.5, 337}, -- CAP
[1280002] = {128, 29.97, 45.83, -35.47}, -- CAP
[1280003] = {129, -991.88, 61.71, -1120.79}, -- CAP
[1280004] = {129, -1883.47, 53.77, -1372.68}, -- CAP
[1280005] = {130, 1123.29, 45.7, -928.69}, -- CAP
[1280006] = {135, -278.181, 77.63, -2260.79}, -- CAP
[1280007] = {128, 582.47, 54.52, -1.2},
[1280008] = {128, 962.836, 46.507, 832.206}, -- Widow Cliffs http://ic.pics.livejournal.com/eijih/14054410/1355/1355_original.jpg
[1280009] = {128, 318, 24.5, 581}, -- Moraby Bay http://ic.pics.livejournal.com/eijih/14054410/1092/1092_original.jpg
[1280010] = {129, -636, 48.8, -1287}, -- Woad Whisper Canyon
[1280011] = {129, -2016.72, 60.055, -766.962}, -- Isles of Umbra http://ic.pics.livejournal.com/eijih/14054410/2243/2243_original.jpg
[1280012] = {130, 1628, 60.3, -449}, -- Tiger Helm Island http://ic.pics.livejournal.com/eijih/14054410/2032/2032_original.jpg
[1280013] = {130, 1522, 1.7, -669},-- Bloodshore http://ic.pics.livejournal.com/eijih/14054410/1607/1607_original.jpg
[1280014] = {130, 1410, 53.3, -1650}, -- Agelyss Wise
[1280015] = {135, -123.315, 60.061, -1438.8}, -- Zelma's Run https://youtu.be/97Ju0Xv-aaQ?t=102
[1280016] = {135, -320.322, 52.835, -1823.68}, -- Bronze Lake http://ic.pics.livejournal.com/eijih/14054410/2503/2503_original.jpg
[1280017] = {135, -894, 41.2, -2188}, -- Oakwood
[1280018] = {131, -1694.5, -19.9, -1534.}, -- Mistbeard Cove
[1280020] = {132, 1343.5, -54.38, -870.84}, -- CAP
--Thanalan
[1280031] = {175, -235, 185, -3.9}, -- CAP
[1280032] = {170, 33, 200.1, -482}, -- Camp Black Brush
[1280033] = {171, 1250.9, 264, -544.2}, -- CAP
[1280034] = {172, -1313.91, 56.023, -145.597}, -- Camp Horizon https://www.youtube.com/watch?v=mQAK4QVnx3c
[1280035] = {173, -165.816, 280.002, -1698.45}, -- Camp Bluefog
[1280036] = {174, 1687.64, 296.002, 992.283}, -- Camp Brokenwater https://www.youtube.com/watch?v=YyBYHg9h2AM
[1280037] = {170, 639, 183.9, 122}, -- Cactus Basin
[1280038] = {170, 539, 215.8, -14}, -- Four Sisters
[1280039] = {171, 1599, 256.7, -233}, -- Halatali
[1280040] = {171, 2010, 280.3, -768}, -- Burning Wall
[1280041] = {171, 2015, 247.8, 64}, -- Sandgate
[1280042] = {172, -864.991, 88.84, 375.18}, -- Nophica's Wells https://www.youtube.com/watch?v=pk4POCDQ9QE
[1280043] = {172, -1653, 24.5, -469}, -- Footfalls
[1280044] = {172, -1220.38, 69.854, 194.365}, -- Scorpion Keep
[1280045] = {173, -635, 280, -1797}, -- Hidden Gorge
[1280046] = {173, 447, 259.1, -2158}, -- Sea of Spires
[1280047] = {173, -710, 280.4, -2212}, -- Cutters Pass
[1280048] = {174, 1797, 248, 1856}, -- Red Labyrinth
[1280049] = {174, 1185, 279.8, 1407}, -- Burnt Lizard Creek
[1280050] = {174, 2416, 248.3, 1535}, -- Zanr'ak
[1280052] = {176, 80.056, 167.929, -1267.94}, -- Nanawa Mines https://www.youtube.com/watch?v=9H-NveJx9EI
[1280054] = {178, -620.374, 110.429, -113.903}, -- Copperbell Mines
-- Black Shroud
[1280061] = {206, -120, 16, -1332}, -- CAP
[1280062] = {150, 288, 4, -543.928}, -- CAP
[1280063] = {151, 1702, 20, -862}, -- CAP
[1280064] = {152, -1052, 20, -1760}, -- CAP
[1280065] = {153, -1566.035, -11.89, -550.51}, -- CAP
[1280066] = {154, 734, -12, 1126}, -- CAP
[1280067] = {150, -94.07, 4, -543.16}, -- Humblehearth
[1280068] = {150, -285, -21.8, -46}, -- Sorrel Haven
[1280069] = {150, 636, 16.2, -324}, -- Five Hangs
[1280070] = {151, 1529.83, 26.991, -1140.15}, -- Verdant Drop
[1280071] = {151, 1296, 47.2, -1534}, -- Lynxpelt Patch
[1280072] = {151, 2297.02, 31.546, -697.828}, -- Larkscall http://www.gwcdn.com/albums/images/4f7ce3a389118b43470005b1.jpg
[1280073] = {152, -883.769, 34.688, -2187.45}, -- Treespeak
[1280074] = {152, -1567, 16.1, -2593}, -- Aldersprings
[1280075] = {152, -800.277, 32, -2785.4}, -- Lasthold
[1280076] = {153, -1908, 0.3, -1042}, -- Lichenweed
[1280077] = {153, -2158, -46.1, -166}, -- Murmur Rills
[1280078] = {153, -1333, -14.2, 324}, -- Turning Leaf
[1280079] = {154, 991, -11.8, 600}, -- Silent Arbor
[1280080] = {154, 1126, -0.1, 1440}, -- Longroot
[1280081] = {154, 189, 0.1, 1337}, -- Snakemolt
[1280082] = {157, -687.916, -15.308, -2063.94}, -- Mun-Tuy Cellars https://www.youtube.com/watch?v=ty6f9Gy0uws
[1280083] = {158, 314.801, -36.2, -167.843}, -- Tam-Tara Deepcroft https://www.youtube.com/watch?v=eLJPTUG-dE0
-- Coerthas
[1280092] = {143, 216, 302.1, -258}, -- Camp Dragonhead
[1280093] = {144, 1122.21, 270.004, -1149.29}, -- Camp Crooked Fork https://www.youtube.com/watch?v=Q7-0r6ELCAU
[1280094] = {145, 1500.78, 206.036, 767.546}, -- Camp Glory
[1280095] = {147, -159.828, 222.037, 1154.81}, -- Camp Ever Lakes https://youtu.be/3wKNidix0Ls?t=274
[1280096] = {148, -1760.36, 270.059, -194.713}, -- Camp Riversmeet https://www.youtube.com/watch?v=gt7Tc9gbTpk
[1280097] = {143, -517, 207.9, 543}, -- Boulder Downs
[1280098] = {143, 190, 367.4, -662}, -- Prominence Point
[1280099] = {143, 960, 287.4, -22}, -- Feathergorge
[1280100] = {144, 1737, 176.5, -1250}, -- Maiden Glen
[1280101] = {144, 1390, 222.6, -736}, -- Hushed Boughs
[1280102] = {144, 1788, 164.8, -829}, -- Scarwing Fall
[1280103] = {145, 1383, 231.8, 422}, -- Weeping Vale
[1280104] = {145, 2160, 142.7, 622}, -- Clearwater
[1280105] = {147, -1, 144.1, 1373}, -- Teriggans Stand
[1280106] = {147, -64, 185.1, 1924}, -- Shepherd Peak
[1280107] = {147, -908, 191.7, 2162}, -- Fellwood
[1280108] = {148, -1734.82, 285.069, -839.63}, -- Wyrmkings Perch
[1280109] = {148, -2366.07, 336.041, -1054.75}, -- The Lance
[1280110] = {148, -2821, 256.1, -290}, -- Twinpools
-- Mor Dhona
[1280121] = {190, 487.445, 18.531, 672.244}, -- Camp Brittlebark https://youtu.be/mkbYeaUqcr4 - I can barely make the ground out
[1280122] = {190, -215.76, 18.54, -668.703}, -- Camp Revenant's Toll
[1280123] = {190, -458, -40.9, -318}, -- Fogfens
[1280124] = {190, 580, 58.2, 206}, -- Singing Shards
[1280125] = {190, -365.724, -18.591, -25.448} -- Jagged Crest Cave
}

117
Data/scripts/ally.lua Normal file
View File

@@ -0,0 +1,117 @@
require ("global")
require ("magic")
require ("weaponskill")
allyGlobal =
{
}
function allyGlobal.onSpawn(ally, target)
end
function allyGlobal.onEngage(ally, target)
end
function allyGlobal.onAttack(ally, target, damage)
end
function allyGlobal.onDamageTaken(ally, attacker, damage)
end
function allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas)
allyGlobal.HelpPlayers(ally, contentGroupCharas)
end
function allyGlobal.onDeath(ally, player, lastAttacker)
end
function allyGlobal.onDespawn(ally)
end
function allyGlobal.HelpPlayers(ally, contentGroupCharas, pickRandomTarget)
print("helpPlayers");
if contentGroupCharas and not ally.IsEngaged() then
print("contentGroup exists");
for chara in contentGroupCharas do
print("looping");
if chara then
-- probably a player, or another ally
-- todo: queue support actions, heal, try pull hate off player etc
if chara.IsPlayer() then
print("chara is a player");
-- do stuff
if not ally.IsEngaged() then
if chara.IsEngaged() then
allyGlobal.EngageTarget(ally, chara.target, nil);
break;
end
end
elseif chara.IsMonster() and chara.IsEngaged() then
if not ally.IsEngaged() then
print("Engaging monster that is engaged");
allyGlobal.EngageTarget(ally, chara, nil);
break;
end
end
end
end
end
end
function allyGlobal.tryAggro(ally, contentGroupCharas)
local count = 0;
if contentGroupCharas and not ally.IsEngaged() then
for i = 0, #contentGroupCharas - 1 do
if contentGroupCharas[i] and ally then
if contentGroupCharas[i].IsPlayer() then
-- probably a player, or another ally
-- todo: queue support actions, heal, try pull hate off player etc
if contentGroupCharas[i].target then
if ally.aiContainer:GetTargetFind():CanTarget(contentGroupCharas[i].target) and contentGroupCharas[i].target.IsMonster() and contentGroupCharas[i].target.hateContainer:HasHateForTarget(contentGroupCharas[i]) then
-- do stuff
allyGlobal.EngageTarget(ally, contentGroupCharas[i].target, nil);
break;
end
end
elseif contentGroupCharas[i].IsMonster() and contentGroupCharas[i].IsEngaged() then
if not ally.IsEngaged() then
print("Engaging monster that is engaged");
allyGlobal.EngageTarget(ally, contentGroupCharas[i], nil);
break;
end
end
end
end
end
end
function allyGlobal.HealPlayer(ally, player)
end
function allyGlobal.SupportAction(ally, player)
end
function allyGlobal.EngageTarget(ally, target, contentGroupCharas)
if contentGroupCharas then
for chara in contentGroupCharas do
if chara.IsMonster() then
if chara.allegiance ~= ally.allegiance then
ally.Engage(chara)
break;
end
end
end
elseif target then
print("Engaging");
ally.Engage(target)
ally.hateContainer.AddBaseHate(target);
end
end

View File

@@ -0,0 +1,19 @@
--[[
PopulaceMenuMan Script
Functions:
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "debugMenuEvent", player);
player:endEvent();
end

View File

@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0, 0, 0;
end

View File

@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0, 0, 0;
end

View File

@@ -0,0 +1,9 @@
require("global");
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
player:EndEvent();
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return false, false, 0, 0, 0, 0;
end

View File

@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0, 303, 10405;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return false, false, 0, 0, 0, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, true, true, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 3, 1, true, false, false, false, false, true, true, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 3, 1, false, false, false, false, false, true, true, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, false, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return true, true, 10, 0, 1, true, false, false, false, false, false, false, false, 0;
end

View File

@@ -0,0 +1,19 @@
require ("global")
--[[
BgKeepout Script
Used to send a msg to the player that they cannot proceed passed this point. Invisible walls are
linked to this object.
]]
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
player:SendGameMessage(player, GetWorldMaster(), 60001, 0x20);
player:EndEvent();
end

View File

@@ -0,0 +1,10 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "bookTalk");
player:EndEvent();
end

View File

@@ -0,0 +1,95 @@
require ("global")
--[[
Elevator Standard Script
Functions:
elevatorAskLimsa001(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Crow's Head Lift Lvl 1.
elevatorAskLimsa002(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Crow's Head Lift Lvl 2.
elevatorAskLimsa003(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Crow's Head Lift Lvl 3.
elevatorAskUldah001(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Wellhead Lift Lvl 1.
elevatorAskUldah002(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Wellhead Lift Lvl 2.
elevatorAskUldah003(eventNum) - Shows the ask dialog, and plays the event cutscenes for the Wellhead Lift Lvl 3.
elevatorQuestAskEvent(questId) - Special quest related elevator dialog.
Notes:
Script to control the elevators in Limsa Lominsa and Ul'dah. Each elevator entrance has a specific event for it's floor.
The only param is used to either show the ask dialog to the player or player the appropriate cutscene given the choice
made.
--]]
function onEventStarted(player, npc, eventType, eventName)
local actorClassId = npc.GetActorClassId();
-- Limsa; Crow's Lift Level 1
if (actorClassId == 1290007) then
local floorChoice = callClientFunction(player, "elevatorAskLimsa001", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskLimsa001", 1);
endEventAndWarp(player, 133, -447, 40, 220, -1.574);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskLimsa001", 2);
endEventAndWarp(player, 133, -458, 92, 175, -0.383);
end
-- Limsa; Crow's Lift Level 2
elseif (actorClassId == 1290008) then
local floorChoice = callClientFunction(player, "elevatorAskLimsa002", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskLimsa002", 1);
endEventAndWarp(player, 133, -447, 19, 220, -1.574);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskLimsa002", 2);
endEventAndWarp(player, 133, -458, 92, 175, -0.383);
end
-- Limsa; Crow's Lift Level 3
elseif (actorClassId == 1290009) then
local floorChoice = callClientFunction(player, "elevatorAskLimsa003", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskLimsa003", 1);
endEventAndWarp(player, 133, -447, 19, 220, -1.574);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskLimsa003", 2);
endEventAndWarp(player, 133, -447, 40, 220, -1.574);
end
-- Ul'dah; Wellhead Lift Level 1
elseif (actorClassId == 1090460) then
local floorChoice = callClientFunction(player, "elevatorAskUldah001", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskUldah001", 1);
endEventAndWarp(player, 209, -116.78, 222, 115.7, 2.85);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskUldah001", 2);
endEventAndWarp(player, 209, -121.60, 269.8, 135.28, -0.268);
end
-- Ul'dah; Wellhead Lift Level 2
elseif (actorClassId == 1090461) then
local floorChoice = callClientFunction(player, "elevatorAskUldah002", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskUldah002", 1);
endEventAndWarp(player, 175, -116.78, 198, 115.7, -2.8911);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskUldah002", 2);
endEventAndWarp(player, 209, -121.60, 269.8, 135.28, -0.268);
end
-- Ul'dah; Wellhead Lift Level 3
elseif (actorClassId == 1090462) then
local floorChoice = callClientFunction(player, "elevatorAskUldah003", 0);
if (floorChoice == 1) then
callClientFunction(player, "elevatorAskUldah003", 1);
endEventAndWarp(player, 175, -116.78, 198, 115.7, -2.8911);
elseif (floorChoice == 2) then
callClientFunction(player, "elevatorAskUldah003", 2);
endEventAndWarp(player, 209, -116.78, 222, 115.7, 2.85);
end
end
end
function endEventAndWarp(player, zoneId, x, y, z, rotation)
player:EndEvent();
GetWorldManager():DoZoneChange(player, zoneId, nil, 0, 15, x, y, z, rotation);
end

View File

@@ -0,0 +1,43 @@
--[[
GuildleveWarpPoint Script
Functions:
eventGuildleveReward(glId, completionTimeSec, completeReward, difficultyBonus, faction, gil???, factionBonus, RewardId1, RewardAmount1, RewardId2, RewardAmount2, difficulty) - Open Reward Dialog
eventTalkGuildleveWarp(returnAetheryteID1, returnAetheryte2) - Opens choice menu
--]]
require ("global")
require ("aetheryte")
require ("utils")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local currentGLDirector = player:GetGuildleveDirector();
local glData = currentGLDirector.guildleveData;
callClientFunction(player, "eventGuildleveReward", currentGLDirector.guildleveId, currentGLDirector.completionTime, 24, 24, 0, 0, 0, 0, 0, 0, 0, currentGLDirector.selectedDifficulty);
local choice = callClientFunction(player, "eventTalkGuildleveWarp", glData.aetheryte, 0);
if (choice == 3) then
local destination = aetheryteTeleportPositions[glData.aetheryte];
if (destination ~= nil) then
randoPos = getRandomPointInBand(destination[2], destination[4], 3, 5);
rotation = getAngleFacing(randoPos.x, randoPos.y, destination[2], destination[4]);
GetWorldManager():DoZoneChange(player, destination[1], nil, 0, 2, randoPos.x, destination[3], randoPos.y, rotation);
currentGLDirector:EndDirector();
end
elseif (choice == 4) then
currentGLDirector:EndDirector();
end
player:EndEvent();
end
--50023: GL COMPLETE!
--50132: You earn faction credits from X

View File

@@ -0,0 +1,163 @@
--[[
MarketEntrance Script
Functions:
Parameters mostly rely on the xtx_placeName sheet for its strings.
eventPushChoiceAreaOrQuest(
exitPlaceName[Fronds, etc], - Retail only showed it when inside a Market Ward/Office Set to 0 to hide the menu.
showMarketWards/Houses - If > 0, client script adds nation-specific Mercentile Houses as well.
gcHQPlaceName, - Set to the placeName id for the Grand Company office of that city
questAreaName, - Set to the placeName id of applicable quest instance, ex. Sailors Ward.
showItemSearchCounter, - If true, shows the Item Search menu
itemSearchId - If > 0 & showItemSearchCounter = true, displays the item name with a "Stop Searching"
)
eventPushStepPrvMarket(
staringWard, - Sets the starting placeName id
wardCount, - Valid number 1-20. Sets the amount of market ward entries. Client continues sequentially from startingWard id.
excludeWard - Hides the ward in the list that matches the id. Use on the ward you're currently in.
)
MarketEntrance City TriggerBox details
Limsa - !warp 230 -416.5 40 446 ActorClass Id = 1090238
bgObj Id - [0xB3B] 2875
Layout Id - [0x79 ] 121 (0x29d90001)
Condition - in
reactName - dwti - Not a typo compared to the other cities
Gridania - !warp 206 -192.57 23.48 -1407.58 ActorClass Id = 1090264
bgObj Id - [0xCFA] 3322
Layout Id - [0x141] 321 (0x29b00001)
Condition - in
reactName - dtwi
Ul'dah - !warp 175 -235 189 50.5 ActorClass Id = 1500394
bgObj Id - [0x102F] 4143
Layout Id - [0x1A5] 421 (0x615a0001)
Condition - in
reactName - dtwi
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
CITY_INFO = { -- wardPlaceName, exitPlaceName, gcHQPlaceName, questAreaName, wardListStart, wardListCount
{1093, 1087, 1512, 1091, 1261, 20}, -- Limsa
{2099, 2091, 2526, 2095, 2261, 20}, -- Gridania
{3098, 3091, 3514, 3095, 3261, 20}, -- Ul'dah
}
-- TO-DO: Add some X/Z pos jitter to Entrances/Exits when called
MARKETWARD_ENTRANCE = {
{134, 160, 0, 135}, -- Limsa Market
{160, 160, 0, 138}, -- Gridania Market
{180, 160, 0, 185} -- Ul'dah Market
}
MARKETWARD_EXIT = {
{230, -420, 41, 435, -3.14}, -- Educated guess for Limsa, need video reference to confirm
{206, -180, 22, -1408, 1.5},
{175, -210, 190, 25, 0.65}
}
GC_ENTRANCE = {
[1512] = {232, 160, 0, -155}, -- Maelstrom Command
[2526] = {234, 160, 0, -155}, -- Adders' Nest
[3514] = {233, 160, 0, -155} -- Hall of Flames
}
city = {
[1090238] = 1, -- Limsa Market Ward Entrance
[1090264] = 2, -- Gridania Market Ward Entrance
[1090265] = 3, -- Ul'dah Market Ward Entrance
[1500392] = 1, -- Limsa : M'septha
[1500393] = 2, -- Gridania : Torsefers
[1500394] = 3, -- Ul'dah : Edine
}
function onEventStarted(player, npc, eventType, eventName)
local npcCity = city[npc:GetActorClassId()] or 1;
local marketPlaceName = CITY_INFO[npcCity][1]; -- Market Wards category name. Identical in all languages except Japanese
local exitPlaceName = CITY_INFO[npcCity][2]; -- Central Limsa Lominsa / Heartstream / The Fronds
local gcHQPlaceName = CITY_INFO[npcCity][3]; -- Maelstrom Command / Adders' Nest / Hall of Flames
local questPlaceName = CITY_INFO[npcCity][4]; -- Sailors Ward / Peasants Ward / Merchants Ward
local wardListStart = CITY_INFO[npcCity][5]; -- Starting id for the market wards
local wardListCount = CITY_INFO[npcCity][6]; -- Amount of wards in the list
local showItemSearchCounter = false;
local itemSearchId = 11000125;
local worldMaster = GetWorldMaster();
local pos = player:GetPos();
local currZone = pos[5];
local currRegion = player.CurrentArea.RegionId;
local quests = player:GetQuestsForNpc(npc);
-- City entrance specific stuff
if (currRegion == 101 or currRegion == 103 or currRegion == 104) then
exitPlaceName = 0; -- If in city, hide city menu option
-- If no quests attached to this entrence, don't show quest area
if (#quests == 0) then
questPlaceName = 0;
end
end
-- If in GC Office, hide office menu option
if (currZone == 232 or currZone == 234 or currZone == 233) then
gcHQPlaceName = 0;
end
choice = callClientFunction(player, "eventPushChoiceAreaOrQuest", exitPlaceName, marketPlaceName, gcHQPlaceName, questPlaceName, showItemSearchCounter, itemSearchId);
while (true) do
if choice == marketPlaceName then -- Market Wards
wardSelect = callClientFunction(player, "eventPushStepPrvMarket", wardListStart, wardListCount, 0);
if wardSelect and (wardSelect >= wardListStart and wardSelect <= (wardListStart+wardListCount)) then
player:SendGameMessage(player, worldMaster, 60004, 0x20, wardSelect);
warp = MARKETWARD_ENTRANCE[npcCity];
playerRot = math.random(-3.14, 3.14);
wait(1);
GetWorldManager():DoZoneChange(player, warp[1], nil, 0, 0x02, warp[2], warp[3], warp[4], playerRot);
player:SendDataPacket("attention", worldMaster, "", 60003, wardSelect);
-- Temp: Pop-up display after Ward zone-in. Client should automate this with PrivateArea's properly setup
break;
end
elseif (choice == 1519 or choice == 2534 or choice == 3533) then -- Mercentile Wards
player:SendMessage(0x20, "", "[MarketEntrance] DEBUG: "..choice);
elseif (choice == 1512 or choice == 2526 or choice == 3514) then -- GC Office
warp = GC_ENTRANCE[choice];
player:SendGameMessage(player, worldMaster, 60004, 0x20, choice);
wait(1);
GetWorldManager():DoZoneChange(player, warp[1], nil, 0, 0x02, warp[2], warp[3], warp[4], math.pi);
break;
elseif (choice == 1087 or choice == 2091 or choice == 3091) then -- Exiting to City
player:SendGameMessage(player, worldMaster, 60004, 0x20, choice);
warp = MARKETWARD_EXIT[npcCity];
wait(1);
GetWorldManager():DoZoneChange(player, warp[1], nil, 0, 0x02, warp[2], warp[3], warp[4], warp[5]);
break;
elseif (choice == 2095 or choice == 3095) then -- Quest
quests[1]:OnPush(player, npc, eventName);
return;
elseif (choice == 0 or choice == -3) then -- Menu Closed
break;
end
choice = callClientFunction(player, "eventPushChoiceAreaOrQuest", exitPlaceName, marketPlaceName, gcHQPlaceName, questAreaName, showItemSearchCounter, itemSearchId);
end
player:EndEvent();
end

View File

@@ -0,0 +1,10 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "materiabookTalk");
player:EndEvent();
end

View File

@@ -0,0 +1,19 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
harvestJudge = GetStaticActor("HarvestJudge");
--callClientFunction(player, "delegateEvent", player, harvestJudge, "loadTextData", dummy);
--callClientFunction(player, "delegateEvent", player, harvestJudge, "targetCancel", dummy);
--callClientFunction(player, "delegateEvent", player, harvestJudge, "turnToTarget", dummy, 0);
--callClientFunction(player, "delegateEvent", player, harvestJudge, "openInputWidget", 22002, 1);
--callClientFunction(player, "delegateEvent", player, harvestJudge, "textInputWidget", harvestJudge, 22002, npc, false);
--callClientFunction(player, "delegateEvent", player, harvestJudge, "askInputWidget", harvestJudge, 22002, 1);
player:EndEvent();
end

View File

@@ -0,0 +1,63 @@
require ("global")
DREAM_ITEM = {
{[1] = 3010419, [2] = 3010420, [3] = 3010421}, -- Mizzenmast/Roost/Hourglass Biscuit
3010003, -- Boiled Egg
3010101, -- Grilled Carp
3010001, -- Meat Miq'abob
3010402, -- Ginger Cookie
3020001, -- Potion
3020101, -- Ether
1000003, -- 5x Crystal Shards (Fire)
1000004, -- 5x Crystal Shards (Ice)
1000005, -- 5x Crystal Shards (Wind)
1000006, -- 5x Crystal Shards (Earth)
1000007, -- 5x Crystal Shards (Lightning)
1000008 -- 5x Crystal Shards (Water)
}
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local choice = callClientFunction(player, "askLogout", player);
-- Quit
if (choice == 2) then
player:SetSleeping();
player:QuitGame();
-- Logout
elseif (choice == 3) then
player:SetSleeping();
player:Logout();
-- Heck the bed
elseif (choice == 4) then
-- Give items based on dream
local dreamCode = player:GetLoginDreamCode();
if (dreamCode >= 21 and dreamCode <= 33) then
local innCode = player:GetInnCode();
local itemCode = DREAM_ITEM[dreamCode - 20];
-- Get biscuit for inn
if (dreamCode == 21) then
itemCode = itemCode[innCode];
end
-- If crystals you get x5 otherwise x1.
if (dreamCode > = 28 and dreamCode <= 33) then
player:AddItem(itemCode, 5);
else
player:AddItem(itemCode, 1);
end
-- Clear the code so they player doesn't keep getting things
player:SetLoginDreamCode(0);
else
-- Otherwise show standard message
player:SendGameMessage(player, npc, 7, 0x20);
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,52 @@
--[[
ObjectEventDoor Script
Functions:
eventDoorMoveAsk() - Shows confirm to move into event
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local choice = callClientFunction(player, "eventDoorMoveAsk");
if (choice == 1) then
local activeQuests = player:GetQuestsForNpc(npc);
-- Either let the player choose the quest or start it if it's the only one.
local chosenQuest;
if (#activeQuests > 1) then
local currentPage = 0;
local numPages = math.floor((#activeQuests-1)/4) + 1;
while (true) do
local page, index = callClientFunction(player, "switchEvent", activeQuests[currentPage * 4 + 1], activeQuests[currentPage * 4 + 2], possibleQuests[currentPage * 4 + 3], possibleQuests[currentPage * 4 + 4], currentPage + 1, numPages, 0x3F1);
if (page == 0) then
chosenQuest = activeQuests[(currentPage * 4) + index];
break;
elseif (page > 0) then
currentPage = page - 1;
else
player:EndEvent();
return;
end
end
elseif (#activeQuests == 1) then
chosenQuest = activeQuests[1];
end
if (chosenQuest ~= nil) then
chosenQuest:OnPush(player, npc, eventName);
return;
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,16 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
defaultFst = GetStaticActor("DftFst");
choice = callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithInn_ExitDoor", nil, nil, nil);
if (choice == 1) then
GetWorldManager():DoZoneChange(player, 1);
end
player:EndEvent();
end

View File

@@ -0,0 +1,54 @@
--[[
ObjectItemStorage Script
Functions:
storageMenu() - Shows store/retrieve/help menu.
selectCategory() - Shows the category menu
selectStoreItem(nil, categoryId) - Shows store item menu
selectReceiveItem(nil, categoryId) - Shows retrieve item menu
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
::TOP_MENU::
storageChoice = callClientFunction(player, "storageMenu");
if (storageChoice == 1) then
categoryChoice = callClientFunction(player, "selectCategory");
if (categoryChoice == 5) then
goto TOP_MENU;
end
itemId = callClientFunction(player, "selectStoreItem", nil, categoryChoice);
if (itemId ~= nil) then
player:GetItemPackage(INVENTORY_NORMAL):RemoveItem(itemId, 1);
end
elseif (storageChoice == 2) then
categoryChoice = callClientFunction(player, "selectCategory");
if (categoryChoice == 5) then
goto TOP_MENU;
end
itemId = callClientFunction(player, "selectReceiveItem", nil, categoryChoice);
if (itemId ~= nil) then
player:GetItemPackage(INVENTORY_NORMAL):AddItem(itemId, 1);
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,6 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end

View File

@@ -0,0 +1,15 @@
require("global");
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
if (triggerName == "caution") then
worldMaster = GetWorldMaster();
player:SendGameMessage(player, worldMaster, 34109, 0x20);
elseif (triggerName == "exit") then
GetWorldManager():DoPlayerMoveInZone(player, 356.09, 3.74, -701.62, -1.4);
end
player:EndEvent();
end

View File

@@ -0,0 +1,18 @@
require("global");
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
if (eventType == ETYPE_PUSH) then
if (eventName == "caution") then
worldMaster = GetWorldMaster();
player:SendGameMessage(player, worldMaster, 34109, 0x20);
elseif (eventName == "exit") then
GetWorldManager():DoPlayerMoveInZone(player, 5.36433, 196, 133.656, -2.84938);
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,9 @@
require("global");
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
player:EndEvent();
end

View File

@@ -0,0 +1,9 @@
require("global");
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
player:EndEvent();
end

View File

@@ -0,0 +1,37 @@
require("global");
--[[
PrivateAreaPastExit
This object contains the player inside a PrivateAreaPast, stopping them from escaping it's bounds. It is the
object that generates the circle graphic on the minimap. This object always has two push triggers, an inner
and outer inverted circle. The inner one is named "caution" and the outer one is named "exit". When the player
leaves the inner circle a warning is shown and when they leave the outer circle they either leave the instance
or get warped back to the center.
]]
function init(privAreaExit)
return false, false, 0, 0;
end
function onEventStarted(player, privAreaExit, eventType, eventName)
player:EndEvent();
if (eventName == "caution") then
player:SendGameMessage(player, GetWorldMaster(), 34109, MESSAGE_TYPE_SYSTEM); -- You are about to leave the instance.
elseif (eventName == "exit") then
local area = privAreaExit.CurrentArea;
if (area.IsPrivate()) then
-- If you can leave, warp to public zone and show message.
if (area.CanExitPrivateArea()) then
player:SendGameMessage(player, GetWorldMaster(), 34110, MESSAGE_TYPE_SYSTEM); -- You have left the instance.
--GetWorldManager():WarpToPublicArea(player);
-- Otherwise warp back to the center of the zone.
else
--GetWorldManager():WarpToCharaPosition(player, privAreaExit);
end
end
end
end

View File

@@ -0,0 +1,19 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
isActive = true;
if (isActive) then
choice = callClientFunction(player, "askYesNo");
else
callClientFunction(player, "eventTalkRead");
end
player:EndEvent();
end

View File

@@ -0,0 +1,56 @@
--[[
RetainerFurniture Script
Functions:
eventPushStepOpenRetainerMenu() - Opens menu to choose retainer
eventRingBell() - Plays the bell ring animation
eventPushRetainerCallCaution() - Shows warning that a open bazaar will be closed if retainer chosen
eventTalkRetainerMenu(hasPossessions, showDispatchChoice) - Opens retainer menu.
eventTalkRetainerDismissal(hasPossessions) - Show dismiss confirmation.
eventTalkRetainerMannequin(0:Enable/1:Disable) - Shows dialog to enable/disable modeling.
eventTalkRetainerItemTrade(operationCode) - Operate RetainerTradeWidget. Codes: 1 - Open, 2 - Select Mode, 3 - Close.
eventTalkRetainerItemList(operationCode) - Operate Bazaar Widget. Codes: 1 - Open, 2 - Select Mode, 3 - Close.
eventReturnResult(resultCode, ?) - Redraws the RetainerTrade UI.
eventTalkSelectBazaarStreet(limitsWardChoices) - Shows the dialog to send a retainer to a street. Set to 20.
eventTalkFinish() - Finishs the talk with retainer
eventPlayerTurn(rotation) - Turns the player
--]]
require ("global")
require ("retainer")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
retainerNumber = callClientFunction(player, "eventPushStepOpenRetainerMenu");
if (retainerNumber == nil or retainerNumber == 0) then
player:EndEvent();
return;
end
callClientFunction(player, "eventRingBell");
retainer = player:SpawnMyRetainer(npc, retainerNumber);
while (true) do
choice = callClientFunction(player, "eventTalkRetainerMenu", false, true);
if (choice == 1) then
doItemTrade(player, retainer);
elseif (choice == 2) then
doBazaar(player, retainer);
elseif (choice == 7) then
callClientFunction(player, "eventTalkRetainerMannequin", 0);
elseif (choice == 8) then
callClientFunction(player, "eventTalkSelectBazaarStreet", 20);
else
break;
end
end
player:DespawnMyRetainer();
player:EndEvent();
end

View File

@@ -0,0 +1,108 @@
--[[
TaskBoard
Operates the Task Board actor located in each of the Adventurers' Guilds.
Calls from the Noc000 static actor, which also applies to specific guild NPCs involved in that as well.
Functions: (only including those from Noc000 which apply to the Task Board)
pETaskBoardAskLimsa()
Desc: Show guild menu with valid options for Limsa Lominsa.
Params: None
Returns: Value dictating which item on the list was selected.
pETaskBoardAskUldah()
Desc: Show guild menu with valid options for Ul'dah.
Params: None
Returns: Value dictating which item on the list was selected.
pETaskBoardAskGridania()
Desc: Show guild menu with valid options for Gridania.
Params: None
Returns: Value dictating which item on the list was selected.
pETaskBoardGuild(guildId)
Desc: Plays back a message "The following tasks are available:".
Params: * guildId - Class Id from xtx_text_jobName. EN doesn't make use of it, but JP/DE/FR do. Thanks Koji.
pETaskBoardOrder(recommendedLvl itemId, hq, amount)
Desc: Takes the params and tells the player what the guild still needs turned in.
Params: * recommendedLvl - Recommended level the player be at
* itemId - Id of the item from xtx_itemName
* hq - Quality of item (1 = NQ, 2 = +1, 3 = +2 4 = +3)
* amount - Amount needed (The amount the player needs to turn-in, not the amount guild needs overall)
--]]
require ("global")
local guildItem = {
-- [guildId] = { (recommendedLvl itemId, hq, amount, 2nd-recommendedLvl 2nd-itemId, 2nd-hq, 2nd-amount) }
[29] = {1, 4100604, 1, 1, 10, 4030706, 1, 1}, -- Carpenters'
[30] = {1, 4040004, 1, 1, 10, 4030004, 1, 1}, -- Blacksmiths'
[31] = {1, 6080009, 1, 1, 10, 8070606, 1, 1}, -- Armorers'
[32] = {1, 5020007, 1, 1, 10,10004103, 1, 1}, -- Goldsmiths'
[33] = {1, 4020107, 1, 1, 10, 8031514, 1, 1}, -- Leatherworkers'
[34] = {1, 8030819, 1, 1, 10, 8030821, 1, 1}, -- Weavers'
[35] = {1, 3011530, 1,12, 10, 3020527, 1, 4}, -- Alchemists'
[36] = {1, 3010103, 1, 6, 10, 3011503, 1, 6}, -- Culinarians'
[39] = {1,10009101, 1,10, 10,10001116, 1,10}, -- Miners'
[40] = {1,10005403, 1,10, 10,10008106, 1,10}, -- Botanists'
[41] = {1, 3011106, 1,10, 10, 3011113, 1,10} -- Fishermans'
}
local menuToGuild = { -- Get a guild id from a given task board's Return result
[1] = {0, 30, 31, 36, 41}, -- Limsa
[2] = {0, 29, 33, 40, 0}, -- Gridania
[3] = {0, 32, 34, 35, 39} -- Ul'dah
}
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local questNOC = GetStaticActor("Noc000");
local npcId = npc:GetActorClassId();
while (true) do
local guildId = 0;
if (npcId == 1200193) then -- Limsa
local choice = callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskLimsa");
if (choice == 1 or choice == nil) then
break; -- Exited menu
else
guildId = menuToGuild[1][choice];
end
elseif (npcId == 1200194) then -- Ul'dah
local choice = callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskUldah");
if (choice == 1 or choice == nil) then
break; -- Exited menu
else
guildId = menuToGuild[3][choice];
end
else -- Gridania
local choice = callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskGridania");
if (choice == 1 or choice == nil) then
break; -- Exited menu
else
guildId = menuToGuild[2][choice];
end
end
if (guildId > 0) then
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardGuild", guildId);
local gItem = guildItem[guildId]
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardOrder", unpack(gItem, 1, 4));
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardOrder", unpack(gItem, 5, 8));
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,119 @@
--[[
AetheryteChild Script
Functions:
eventAetheryteChildSelect(showTeleport, parentAetheryteID, animaAmount, animaCost(always 1)): Opens menu
eventAetheryteChildDesion(aetheryteId): "Your homepoint is now X"
eventGLSelect(?) - Open GL selector
eventGLSelectDetail(glid, ?, reward, rewardQuantity, subreward, subrewardQuantity, faction, ?, completed) - Show GL details
eventGLDifficulty() - Open difficulty selector
eventGLStart(glId, difficulty, evaluatingFaction, areaFactionStanding, factionReward, warningBoundByDuty, warningTooFar, warningYouCannotRecieve, warningChangingClass) - Confirmation dialog
eventGLBoost(currentFavor, minNeeded) - Ask player for Guardian Aspect
eventGLPlay(??) - Open Menu (GL active version)
eventGLReward (glId, clearTime, missionBonus, difficultyBonus, factionNumber, factionBonus, factionCredit, reward, rewardQuantity, subreward, subrewardQuantity, difficulty) - Open reward window
eventGLJoin () - Ask to join party leader's leve
--]]
require ("global")
require ("aetheryte")
require ("utils")
require ("guildleve")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, aetheryte, triggerName)
if (player:GetGuildleveDirector() ~= nil) then
doGuildleveMenu(player, aetheryte);
else
doNormalMenu(player, aetheryte);
end
player:EndEvent();
end
function doGuildleveMenu(player, aetheryte)
local currentGLDirector = player:GetGuildleveDirector();
local choice = callClientFunction(player, "eventGLPlay", currentGLDirector.guildleveId, true, 1, 500, 400, guardian, 8, currentGLDirector.selectedDifficulty, 2);
--Abandon
if (choice == 6) then
currentGLDirector:AbandonGuildleve();
end
end
function doNormalMenu(player, aetheryte)
local aetheryteId = aetheryte:GetActorClassId();
local parentNode = aetheryteChildLinks[aetheryteId];
local menuChoice = callClientFunction(player, "eventAetheryteChildSelect", true, parentNode, 100, 1);
--Teleport
if (menuChoice == 2) then
printf("%ud", parentNode);
destination = aetheryteTeleportPositions[parentNode];
if (destination ~= nil) then
randoPos = getRandomPointInBand(destination[2], destination[4], 3, 5);
rotation = getAngleFacing(randoPos.x, randoPos.y, destination[2], destination[4]);
GetWorldManager():DoZoneChange(player, destination[1], nil, 0, 2, randoPos.x, destination[3], randoPos.y, rotation);
end
--Init Levequest
elseif (menuChoice == -1) then
doLevequestInit(player, aetheryte);
--Set Homepoint
elseif (menuChoice == -2) then
player:SetHomePoint(aetheryteId);
callClientFunction(player, "eventAetheryteChildDesion", aetheryteId);
--View Faction Standing
elseif (menuChoice == -3) then
player:SendGameMessage(player, aetheryte, 27, 0x20);
player:SendGameMessage(player, aetheryte, 28, 0x20, 1, 15);
player:SendGameMessage(player, aetheryte, 29, 0x20, 2, 10);
player:SendGameMessage(player, aetheryte, 30, 0x20, 3, 5);
end
end
function doLevequestInit(player, aetheryte)
local worldMaster = GetWorldMaster();
::SELECT_LOOP::
unknown, glId = callClientFunction(player, "eventGLSelect", 0x0);
if (glId ~= 0) then
::SELECT_DETAIL::
guildleveData = GetGuildleveGamedata(glId);
if (guildleveData == nil) then
player:SendMessage(0x20, "", "An error has occured... aborting.");
return;
end
unknown, begin = callClientFunction(player, "eventGLSelectDetail", glId, 0xa, 0xf4241, 1000, 0, 0, 0, true, false);
if (begin) then
::SELECT_DIFFICULTY::
player:SendGameMessage(worldMaster, 50014, 0x20); --"Please select a difficulty level. This may be lowered later."
difficulty = callClientFunction(player, "eventGLDifficulty", glId);
if (difficulty == nil) then goto SELECT_DETAIL; end
confirmResult = callClientFunction(player, "eventGLStart", glId, difficulty, 1, 10, 20, 0, 0, 0, 0);
if (confirmResult == nil) then goto SELECT_DIFFICULTY; else
player:SendGameMessage(worldMaster, 50036, 0x20, glId, player);
player:PlayAnimation(getGLStartAnimationFromSheet(guildleveData.borderId, guildleveData.plateId, true));
director = player.CurrentArea:CreateGuildleveDirector(glId, difficulty, player);
player:AddDirector(director);
director:StartDirector(true, glId)
end
else
goto SELECT_LOOP;
end
end
end

View File

@@ -0,0 +1,178 @@
--[[
AetheryteParent Script
Functions:
eventAetheryteParentSelect(showTeleportMenu, animaAmount, gate1, gate2, gate3, gate4, gate5) - Open Menu
eventAetheryteParentDesion(sheetId) - Show Homepoint Set Message
eventGLSelect(?) - Open GL selector
eventGLSelectDetail(glid, ?, reward, rewardQuantity, subreward, subrewardQuantity, faction, ?, completed) - Show GL details
eventGLDifficulty() - Open difficulty selector
eventGLStart(glId, difficulty, evaluatingFaction, areaFactionStanding, factionReward, warningBoundByDuty, warningTooFar, warningYouCannotRecieve, warningChangingClass) - Confirmation dialog
eventGLBoost(currentFavor, minNeeded) - Ask player for Guardian Aspect
eventGLPlay(glId, showLeveLink, leveLinkFaction, leveLinkFactionStanding, leveLinkReward, guardianFavorAmount, guardianFavorNeeded, currentDifficulty, jobNameForChange) - Open Menu (GL active version)
eventGLReward (glId, clearTime, missionBonus, difficultyBonus, factionNumber, factionBonus, factionCredit, reward, rewardQuantity, subreward, subrewardQuantity, difficulty) - Open reward window
eventGLJoin () - Ask to join party leader's leve
--callClientFunction(player, "eventGLBoost", 0xc8, 0xb);
--callClientFunction(player, "eventGLReward", 0x2a48, 120, 123, 125, 1, 111, 0, 0xf4241, 5, 0, 0, 3);
--]]
require ("global")
require ("aetheryte")
require ("utils")
require ("guildleve")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, aetheryte, triggerName)
-- Main Scenario Intro Quests
if (player:HasQuest(110002) == true) then
require ("quests/man/man0l1");
local quest = player:GetQuest("Man0l1");
if (quest:GetSequence() == SEQ_003) then
callClientFunction(player, "delegateEvent", player, quest, "processEvent025");
quest:StartSequence(SEQ_005);
end
elseif (player:HasQuest(110006) == true) then
require ("quests/man/man0g1");
local quest = player:GetQuest("Man0g1");
if (quest:GetSequence() == SEQ_005) then
callClientFunction(player, "delegateEvent", player, quest, "processEvent013");
--quest:StartSequence(???);
end
elseif (player:HasQuest(110010) == true) then
require ("quests/man/man0u1");
local quest = player:GetQuest("Man0u1");
if (quest:GetSequence() == SEQ_005) then
callClientFunction(player, "delegateEvent", player, quest, "processEvent013");
quest:StartSequence(SEQ_010);
end
end
if (player:GetGuildleveDirector() ~= nil) then
doGuildleveMenu(player, aetheryte);
else
doNormalMenu(player, aetheryte);
end
player:EndEvent();
end
function doGuildleveMenu(player, aetheryte)
local currentGLDirector = player:GetGuildleveDirector();
local choice = callClientFunction(player, "eventGLPlay", currentGLDirector.guildleveId, true, 1, 500, 400, guardian, 8, currentGLDirector.selectedDifficulty, 2);
--Abandon
if (choice == 6) then
currentGLDirector:AbandonGuildleve();
end
end
function doNormalMenu(player, aetheryte)
local aetheryteId = aetheryte:GetActorClassId();
local childNodes = aetheryteParentLinks[aetheryteId];
local listPosition = 1;
local activeChildNodes = {0, 0, 0, 0, 0};
if (childNodes ~= nil) then
if (player:HasAetheryteNodeUnlocked(childNodes[1])) then
activeChildNodes[listPosition] = childNodes[1];
listPosition = listPosition+1;
end
if (player:HasAetheryteNodeUnlocked(childNodes[2])) then
activeChildNodes[listPosition] = childNodes[2];
listPosition = listPosition+1;
end
if (player:HasAetheryteNodeUnlocked(childNodes[3])) then
activeChildNodes[listPosition] = childNodes[3];
listPosition = listPosition+1;
end
if (player:HasAetheryteNodeUnlocked(childNodes[4])) then
activeChildNodes[listPosition] = childNodes[4];
listPosition = listPosition+1;
end
if (player:HasAetheryteNodeUnlocked(childNodes[5])) then
activeChildNodes[listPosition] = childNodes[5];
listPosition = listPosition+1;
end
end
local showTeleportOptions = true;
if (listPosition == 1) then
showTeleportOptions = false;
end
local choice = callClientFunction(player, "eventAetheryteParentSelect", showTeleportOptions, 100, activeChildNodes[1], activeChildNodes[2], activeChildNodes[3], activeChildNodes[4], activeChildNodes[5]);
if (choice ~= nil) then
--Init Leavequest
if (choice == -1) then
doLevequestInit(player, aetheryte);
--Set Homepoint
elseif (choice == -2) then
player:SetHomePoint(aetheryteId);
callClientFunction(player, "eventAetheryteParentDesion", aetheryteId);
--View Faction Standings
elseif (choice == -3) then
player:SendGameMessage(player, aetheryte, 124, 0x20);
player:SendGameMessage(player, aetheryte, 125, 0x20, 1, 15);
player:SendGameMessage(player, aetheryte, 126, 0x20, 2, 10);
player:SendGameMessage(player, aetheryte, 127, 0x20, 3, 5);
--Teleport to Gate
elseif (choice > 0) then
destination = aetheryteTeleportPositions[activeChildNodes[choice]];
if (destination ~= nil) then
randoPos = getRandomPointInBand(destination[2], destination[4], 3, 5);
rotation = getAngleFacing(randoPos.x, randoPos.y, destination[2], destination[4]);
GetWorldManager():DoZoneChange(player, destination[1], nil, 0, 2, randoPos.x, destination[3], randoPos.y, rotation);
end
end
end
end
function doLevequestInit(player, aetheryte)
local worldMaster = GetWorldMaster();
::SELECT_LOOP::
unknown, glId = callClientFunction(player, "eventGLSelect", 0x0);
if (glId ~= 0) then
::SELECT_DETAIL::
guildleveData = GetGuildleveGamedata(glId);
if (guildleveData == nil) then
player:SendMessage(0x20, "", "An error has occured... aborting.");
return;
end
unknown, begin = callClientFunction(player, "eventGLSelectDetail", glId, 0xa, 0xf4241, 1000, 0, 0, 0, true, false);
if (begin) then
::SELECT_DIFFICULTY::
player:SendGameMessage(worldMaster, 50014, 0x20); --"Please select a difficulty level. This may be lowered later."
difficulty = callClientFunction(player, "eventGLDifficulty", glId);
if (difficulty == nil) then goto SELECT_DETAIL; end
confirmResult = callClientFunction(player, "eventGLStart", glId, difficulty, 1, guildleveData.favorCount, 20, 0, 0, 0, 0);
if (confirmResult == nil) then goto SELECT_DIFFICULTY; else
player:SendGameMessage(worldMaster, 50036, 0x20, glId, player);
player:PlayAnimation(getGLStartAnimationFromSheet(guildleveData.borderId, guildleveData.plateId, true));
director = player.CurrentArea:CreateGuildleveDirector(glId, difficulty, player);
player:AddDirector(director);
director:StartDirector(true, glId);
end
else
goto SELECT_LOOP;
end
end
end

View File

@@ -0,0 +1,25 @@
--[[
PopulaceAchievement Script
Functions:
eventNoGC() -
eventUnlock(sheetId) -
eventReward(?, bool, ?, bool) -
defTalk() - Blurb
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "defTalk");
player:EndEvent();
end

View File

@@ -0,0 +1,159 @@
--[[
PopulaceBlackMarketeer Script
Functions:
eventTalkWelcome(player) - Start Text
eventSellItemAsk(player, itemName, tradePrice) - Requires GC Affiliation. Trade menu for Commemorative Coin
eventAskMainMenu(player, index) - Shows menu prompt to purchase with gil or with GC seals
eventTalkBye(player) - Says bye text
eventTalkStepBreak() - Ends talk, NPC turns to face original position
eventSealShopMenuOpen() - Opens menu for purchasing with grand company seals
eventSealShopMenuAsk() - Returns two values, one that seems to always be true, and an index of purchased item
eventSealShopMenuClose() - Closes seal menu
eventGilShopMenuOpen() - Opens menu for purchasing with gil
eventGilShopMenuAsk() - Returns two values, one that seems to always be true, and an index of purchased item
eventGilShopMenuClose() - Closes gil menu
Class applies to only three NPCs
Actorclass Id - 1500293 : Momoroon, Limsa Lominsa
Actorclass Id - 1500294 : Gagaroon, Gridania
Actorclass Id - 1500295 : Lalaroon, Ul'dah
--]]
require ("global")
require ("shop")
shopInfo = { -- [ index ] = { itemId, gilPrice, sealPrice, city, itemCategory }
[1001] = {3020202, 100, 10000, 1, 1},
[1002] = {3020509, 400, 40000, 1, 1},
[1003] = {3020510, 400, 40000, 1, 1},
[1004] = {3020504, 1000, 100000, 1, 1},
[1005] = {3020505, 1000, 100000, 1, 1},
[1101] = {9040018, 1500, 150000, 1, 2},
[1102] = {9010025, 2000, 200000, 1, 2},
[1301] = {2001014, 4000, 400000, 1, 4},
[2001] = {3020203, 100, 10000, 2, 1},
[2002] = {3020509, 400, 40000, 2, 1},
[2003] = {3020510, 400, 40000, 2, 1},
[2004] = {3020504, 1000, 100000, 2, 1},
[2005] = {3020505, 1000, 100000, 2, 1},
[2101] = {9040018, 1500, 150000, 2, 2},
[2102] = {9010025, 2000, 200000, 2, 2},
[2301] = {2001015, 4000, 400000, 2, 4},
[3001] = {3020204, 100, 10000, 3, 1},
[3002] = {3020509, 400, 40000, 3, 1},
[3003] = {3020510, 400, 40000, 3, 1},
[3004] = {3020504, 1000, 100000, 3, 1},
[3005] = {3020505, 1000, 100000, 3, 1},
[3101] = {9040018, 1500, 150000, 3, 2},
[3102] = {9010025, 2000, 200000, 3, 2},
[3301] = {2001016, 4000, 400000, 3, 4},
}
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
commemorativeCoin = 10011251;
commemorativeCoinValue = 25000;
gilCurrency = 1000001;
playerGC = player.gcCurrent
playerGCSeal = 1000200 + playerGC;
callClientFunction(player, "eventTalkWelcome", player);
if player:GetItemPackage(INVENTORY_NORMAL):HasItem(commemorativeCoin) and playerGC > 0 then
-- Checks for player having a commemorative coin, show window trade option if so.
coinChoice = callClientFunction(player, "eventSellItemAsk", player, commemorativeCoin, commemorativeCoinValue);
if coinChoice == 1 then
currencyType = callClientFunction(player, "eventAskMainMenu", player);
elseif coinChoice == 2 then
-- You trade <itemQuantity1> <itemName1> <itemQuality1> for <itemQuantity2> <itemName2> <itemQuality2>.
player:SendGameMessage(player, GetWorldMaster(), 25071, MESSAGE_TYPE_SYSTEM, commemorativeCoin, 1, playerGCSeal, 1, 1, commemorativeCoinValue);
player:GetItemPackage(INVENTORY_NORMAL):RemoveItem(commemorativeCoin, 1);
player:GetItemPackage(INVENTORY_CURRENCY):addItem(playerGCSeal, 25000, 1)
-- TODO: Add handling for checking GC seals limit and not going over it
end
else
-- If no grand company alignment, go straight to the shop that uses gil, otherwise show gc seal option.
if playerGC == 0 then
processGilShop(player);
else
currencyType = callClientFunction(player, "eventAskMainMenu", player);
if currencyType == 1 then
processGilShop(player);
elseif currencyType == 2 then
processSealShop(player);
end
end
end
callClientFunction(player, "eventTalkBye", player);
callClientFunction(player, "eventTalkStepBreak", player);
player:EndEvent();
end
function processGilShop(player)
callClientFunction(player, "eventGilShopMenuOpen", player);
while (true) do
unk1, buyResult = callClientFunction(player, "eventGilShopMenuAsk", player);
printf(unk1);
if (buyResult == 0 or buyResult == -1) then
callClientFunction(player, "eventGilShopMenuClose", player);
break;
else
if shopInfo[buyResult] == nil then
-- Prevent server crash from someone trying to buy a non-existent item via packet injection.
break;
else
-- TODO: Add handling to check you're on the right NPC to prevent packet injecting a purchase from anything in the list
if shopInfo[buyResult][5] == 4 then
location = INVENTORY_KEYITEMS;
else
location = INVENTORY_NORMAL;
end
purchaseItem(player, location, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][3], gilCurrency);
end
end
end
end
function processSealShop(player)
callClientFunction(player, "eventSealShopMenuOpen", player);
while (true) do
unk1, buyResult = callClientFunction(player, "eventSealShopMenuAsk", player);
if (buyResult == 0 or buyResult == -1) then
callClientFunction(player, "eventSealShopMenuClose", player);
break;
else
if shopInfo[buyResult] == nil then
-- Prevent server crash from someone trying to buy a non-existent item via packet injection.
break;
else
-- TODO: Add handling to check you're on the right NPC to prevent packet injecting a purchase from anything in the list
if shopInfo[buyResult][5] == 4 then
location = INVENTORY_KEYITEMS;
else
location = INVENTORY_NORMAL;
end
purchaseItem(player, location, shopInfo[buyResult][1], 1, 1, shopInfo[buyResult][2], playerGCSeal);
end
end
end
end

View File

@@ -0,0 +1,26 @@
--[[
PopulaceBountyPresenter Script
Functions:
eventLowerLevel(player) -
eventAlreadyPresent(player) -
eventBeforePresent(player) -
eventAfterPresent(player) -
eventJail(player, bool) -
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "eventLowerLevel", player);
player:EndEvent();
end

View File

@@ -0,0 +1,26 @@
--[[
PopulaceBranchVendor Script
Functions:
eventTalkWelcome(player) - Starts talk turn and
eventSearchItemAsk(nil, stopSearchingItemId) -
eventTalkStepBreak() - Finishes the talk turn.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "eventTalkWelcome", player);
callClientFunction(player, "eventSearchItemAsk", nil, 0);
callClientFunction(player, "eventTalkStepBreak", player);
player:EndEvent();
end

View File

@@ -0,0 +1,26 @@
--[[
PopulaceCampMaster Script
Functions:
defTalk(player, favAetheryte1, favAetheryte2, favAetheryte3, playerLevel, ?) - The main and only function for this npc. If favAetheryte1 == 0, will not ask to remove others.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
favLocation = callClientFunction(player, "defTalk", player, 0, 1280004, 1280005);
--if (hasThree) then
--Remove chosen
--end
player:EndEvent();
end

View File

@@ -0,0 +1,31 @@
--[[
PopulaceCampSubMaster Script
Functions:
talkWelcome(player, level, ?) - Main npc function.
confirmUseFacility(player, gilAmount) - Confirm dialog if player uses facility.
finishTalkTurn() - Call to stop the npc staring at player.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
choice = callClientFunction(player, "talkWelcome", player, 1, false);
if (choice == 1) then
confirmed = callClientFunction(player, "confirmUseFacility", player, 1);
end
callClientFunction(player, "finishTalkTurn");
player:EndEvent();
end

View File

@@ -0,0 +1,41 @@
--[[
PopulaceCaravanAdviser Script
Functions:
adviserDeffault() - Not a typo. NPC dialog talking about a chocobo. Resets their sight on you, perhaps used on closing dialog?
adviserAsk() - Brings up a menu for caravan info, or purchasing gysahl greens
adviserAdvise() - NPC dialog discussing feeding chocobos
adviserSales(price) - Gysahl purchase dialog and prompt
adviserBuy() - Dialog to play after purchasing gysahl greens
adviserBuyNG() - NPC plays /shrug animation.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local gysahlPrice = 20;
local choice = callClientFunction(player, "adviserAsk");
if choice == 1 then
callClientFunction(player, "adviserAdvise");
elseif choice == 2 then
local purchaseChoice = callClientFunction(player, "adviserSales", gysahlPrice);
if purchaseChoice == 1 then
callClientFunction(player, "adviserBuy");
elseif purchaseChoice == 2 then
callClientFunction(player, "adviserBuyNG");
end
elseif choice == 3 then
callClientFunction(player, "adviserDeffault")
end
player:EndEvent();
end

View File

@@ -0,0 +1,68 @@
--[[
PopulaceCaravanGuide Script
This script handles the caravan guide class, which is for the actor who escorts the chocobos behind them during Caravan Security events.
Functions:
caravanGuardCancel() - Menu prompt to abandon the caravan
caravanGuardReward(cargo, nil, areaName, playerGC, killCount, areaName2)
- Reward dialog for completing the caravan
- cargo = 0 (none) through 9 (all) for varying degrees of success dialog
- If playerGC doesn't match the GC of the areaName region, NPC mentions you don't need their seals.
- killCount shows an extra dialog if 40-49 enemies were slain, and a different one at 50+
caravanGuardNotReward() - Dialog stating you didn't contribute to the event at all
caravanGuardFailReward(areaName, areaName2) - Failure dialog, NPC offers free gysahl green, then offers free teleport back to aetheryte
caravanGuardThanks(name1, name2, name3) - Dialog for joining the caravan. NPC names the three chocobos. Name IDs from xtx_displayName
caravanGuardOffer(areaName, areaName2, playerGC) - Dialog for who to talk to for joining the caravan.
caravanGuardAmple(areaName, areaName2) - Dialog for NPC taking a break?
caravanGuardSuccess() - Dialog when you reached destination?
caravanGuardFailure(areaName, areaName2) - Failure dialog for mentioned area.
caravanGuardIgnore() - Resets NPC state for player? Or used for players not flagged for the event.
caravanGuardBonusReward(nil, isBonus?) - NPC says variation on a piece of dialog from the boolean passed
caravanGuardNotBonusReward() - Inventory full flavour dialog
Notes:
Functions employing areaName/areaName2 add their value together in the client's script to get the area name. Said area values are...
1 = Wineport, 2 = Quarrymill, 3 = Silver Bazaar, 4 = Aleport, 5 = Hyrstmill, 6 = Golden Bazaar
areaName will always be 1-3 for caravanGuardReward to function as expected for GC-related dialog
areaName2 will always be either 0 or 3. 0 for the lower level caravan area name, 3 for the higher level.
populaceCaravanGuide sheet:
ID Dialog Comment
6 It is time. Come, let us ride. - Caravan begins.
12 We've arrived at last! Come and speak to me when you're ready to claim your reward. - Caravan completed.
23 We're under attack! The chocobos! Protect the chocobos! - Caravan aggros monsters
27 Gods, have we already come this far? At this pace, we stand to make good time. - Says between 50% & 90% of the way to desgination? Can be said more than once per run
28 Well fought, friend. I thank the gods you're with us. Come, onward! - Cleared monsters that caravan aggro'd
TO-DO:
Document actors involved. Should be six of them.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local areaName = 1;
local areaName2 = 3;
local playerGC = 1;
local cargo = 9;
local killCount = 50;
callClientFunction(player, "caravanGuardOffer", areaName, areaName2, playerGC);
--callClientFunction(player, "caravanGuardReward", cargo, nil, areaName, playerGC, killCount, areaName2);
--player:SendGameMessageLocalizedDisplayName(npc, 6, MESSAGE_TYPE_SAY, npc.displayNameId);
player:EndEvent();
end

View File

@@ -0,0 +1,49 @@
--[[
PopulaceCaravanManager Script
Functions:
caravanGuardEntry(areaGC, hasRoomForGCSeals, areaName, difficulty, playerGC, playerCountRequired, levelRequired)
- Dialog for signing up for caravan. areaGC(1-3) & areaName(0 or 3) added together to get location name.
- If difficulty => 40 on areaGC 1-3 & areaName 0, NPC mentions it's be a tougher trip
caravanGuardQuestion(areaName1, areaName2, escortMax, isSameGC?, playerGC?) - Ask about the caravan escort
caravanGuardJoinOK(areaName1, areaName2, playerGC) - Dialog for successfully joining the caravan
caravanGuardJoinNG(nil, maxEscorts, playerGC) - Dialog dictating how many escorts total filled the run.
caravanGuardAmple(nil, playerGC, playerGC) - Dialog for caravan escort being full.
caravanGuardOther(npcGC) - Dialog where NPC mentions you're not part of the given Grand Company parameter
caravanGuardSigh() - NPC does a shrug animation
caravanGuardHuh() - NPC does /huh
caravanGuardCancel(nil, playerGC) - Dialog for canceling caravan escort.
Notes:
Some NPC dialog address you differently if your GC rank is Chief Sergeant (id 27) or higher, but only in non-English languages.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local GC = 3;
local playerGC = 1;
local areaName = 0;
local level = 25;
local playerCount = 8;
local difficulty = 41;
local hasRoomForGCSeals = false;
local isSameGC = true;
local escortMax = 8;
areaName1 = 1;
areaName2 = 3;
-- callClientFunction(player, "caravanGuardCancel", nil, 3);
callClientFunction(player, "caravanGuardEntry", GC, hasRoomForGCSeals, areaName, difficulty, playerGC, playerCount, level);
player:EndEvent();
end

View File

@@ -0,0 +1,136 @@
--[[
PopulaceChocoboLender Script
Functions:
eventTalkWelcome(player) - Start Text
eventAskMainMenu(player, curLevel, hasFundsForRent, isPresentChocoboIssuance, isSummonMyChocobo, isChangeBarding, currentChocoboWare) - Shows the main menu
eventTalkMyChocobo(player) - Starts the cutscene for getting a chocobo
eventSetChocoboName(true) - Opens the set name dialog
eventAfterChocoboName(player) - Called if player done naming chocobo, shows cutscene, returns state and waits to teleport outside city.
eventCancelChocoboName(player) - Called if player cancels naming chocobo, returns state.
eventTalkStepBreak(player) - Finishes talkTurn and says a goodbye
Notes:
* Rent price and time seems to be hardcoded into the client. Price is always 800gil and time is 10m.
* The func eventSetChocoboName *requires* the actor with id `1080101` to be present in the client instance or it will crash (thanks Jorge for finding that).
* Special spawn codes must be sent for getting your chocobo or renting for it to work properly.
--]]
require ("global")
local rentalPrice = 800;
local rentalTime = 10;
local gcIssuances = {
[1500006] = 2001004,
[1500061] = 2001005,
[1000840] = 2001006,
[1500059] = 0
};
local startAppearances = {
[1500006] = CHOCOBO_LIMSA1,
[1500061] = CHOCOBO_GRIDANIA1,
[1000840] = CHOCOBO_ULDAH1
};
local cityExits = {
[1500006] = {133, -6.032, 46.356, 132.572, 3.034},
[1500061] = {150, 333.271, 5.889, -943.275, 0.794},
[1000840] = {170, -26.088, 181.846, -79.438, 2.579},
[1500059] = {172, -2133.028, 15.476, -421.471, 1.5}
};
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local classId = npc:GetActorClassId();
local curLevel = 20; -- TODO: pull from character
local hasIssuance = player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(gcIssuances[classId]);
local hasChocobo = player.hasChocobo;
if (hasChocobo == false) then -- Let GMs auto have the issuance for debugging
hasIssuance = true;
end
local hasFunds = (player:GetCurrentGil() >= rentalPrice);
if ((classId == 1000840) and (player:HasQuest(110009))) then -- Cross-script Man0u0 dialog
local sequence = player:GetQuest(110009):getSequence();
if (sequence == 0) then
callClientFunction(player, "delegateEvent", player, GetStaticActor("Man0u0"), "processEvent000_13");
elseif (sequence == 10) then
callClientFunction(player, "delegateEvent", player, GetStaticActor("Man0u0"), "processEvent020_7");
else
player:EndEvent();
end
else
callClientFunction(player, "eventTalkWelcome", player);
local menuChoice = callClientFunction(player, "eventAskMainMenu", player, curLevel, hasFunds, hasIssuance, hasChocobo, hasChocobo, 0);
if (menuChoice == 1) then -- Issuance option
callClientFunction(player, "eventTalkMyChocobo", player);
local nameResponse = callClientFunction(player, "eventSetChocoboName", true);
if (nameResponse == "") then -- Cancel Chocobo naming
callClientFunction(player, "eventCancelChocoboName", player);
callClientFunction(player, "eventTalkStepBreak", player);
player:EndEvent();
return;
else
local appearance = startAppearances[classId];
player:IssueChocobo(appearance, nameResponse);
callClientFunction(player, "eventAfterChocoboName", player);
--Add Chocobo License and remove issuance
if (player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(2001007) == false) then
player:GetItemPackage(INVENTORY_KEYITEMS):AddItem(2001007);
end
player:GetItemPackage(INVENTORY_KEYITEMS):RemoveItem(gcIssuances[classId], 1);
--Warp with the special chocobo warp mode.
mountChocobo(player);
GetWorldManager():DoZoneChange(player, cityExits[classId][1], nil, 0, SPAWN_CHOCOBO_GET, cityExits[classId][2], cityExits[classId][3], cityExits[classId][4], cityExits[classId][5]);
end
elseif(menuChoice == 2) then -- Summon Bird
mountChocobo(player);
GetWorldManager():DoZoneChange(player, cityExits[classId][1], nil, 0, SPAWN_NO_ANIM, cityExits[classId][2], cityExits[classId][3], cityExits[classId][4], cityExits[classId][5]);
elseif(menuChoice == 3) then -- Change Barding
callClientFunction(player, "eventTalkStepBreak", player);
elseif(menuChoice == 5) then -- Rent Bird
mountChocobo(player, true, 10);
GetWorldManager():DoZoneChange(player, cityExits[classId][1], nil, 0, SPAWN_CHOCOBO_RENTAL, cityExits[classId][2], cityExits[classId][3], cityExits[classId][4], cityExits[classId][5]);
else
callClientFunction(player, "eventTalkStepBreak", player);
end
end
player:EndEvent();
end
function mountChocobo(player, isRental, rentalMinutes)
if (isRental) then
player:ChangeMusic(64);
player:StartChocoboRental(rentalMinutes);
else
player:ChangeMusic(83);
end
player:SendMountAppearance();
player:SetMountState(1);
player:ChangeSpeed(0.0, 3.6, 9.0, 9.0);
player:ChangeState(15);
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

@@ -0,0 +1,77 @@
--[[
PopulaceCompanyOfficer Script
xtx_gcRank for GC Rank values
Functions:
eventTalkWelcome() - Welcome dialog
eventTalkWelcomeQuest() - Same as Welcome dialog?
eventTalkPreJoin() - Dialog for starting GC rank?
eventTalkExclusive() - Dialog to play when you're not of that GC?
eventTalkJoinedOnly() - Reads like chat-end dialog for your GC.
eventTalkJoined(gcRank, gcRank, isCanAfford, isShowPromotion) - Menu to ask about/for promotion
eventDoRankUp(gcRank, gcRank) - Plays rank-up animation and opens GC window.
eventRankUpDone(???, ???) - Has your character do the GC salute? Values seem to do nothing?
eventRankCategoryUpBefore(gcRank) - 11/21/31 - Mentions which GC quest you need to clear to continue promotion
eventRankCategoryUpAfter() - Follow-up dialog after ranking up
eventTalkQuestUncomplete() - Quest prerequisite dialog for ranking up to Second Lieutenant (1.23b rank cap)
eventTalkFestival() - Foundation Day 2011 event dialog. Server needs to reward 1000 GC seals after.
eventTalkFestival2() - Foundation Day 2011 event dialog. Seems to reward more seals, unsure how many.
eventTalkFestival2012(value) - Foundation Day 2012 event dialog. Rewards amount of seals dictated by value, retail used 5000.
eventTalkStepBreak() - Resets NPC target/facing
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
gcOfficer = {
[1500199] = 1, -- Limsa Officer
[1500200] = 2, -- Grid Officer
[1500198] = 3, -- Flame Officer
}
function onEventStarted(player, npc, triggerName)
playerGC = player.gcCurrent;
playerGCSeal = 1000200 + playerGC;
playerCurrentRank = 13;
playerRankUpCost = 1500;
playerNextRank = 15;
currentRankCap = 31; -- Second Lieutenant
npcId = npc:GetActorClassId();
if playerGC == gcOfficer[npcId] then
callClientFunction(player, "eventTalkWelcome");
if playerCurrentRank < currentRankCap then
if player:GetItemPackage(INVENTORY_CURRENCY):HasItem(playerGCSeal, playerRankUpCost) then
-- Show Promotion window, allow paying
local choice = callClientFunction(player, "eventTalkJoined", playerCurrentRank, playerNextRank, true, true);
-- If promotion accepted
if choice == 1 then
callClientFunction(player, "eventDoRankUp", playerNextRank, playerNextRank);
-- TODO: Table GC info or get it in source/sql. Handle actual upgrade of GC rank/seal cap/cost/etc.
end
else
-- Show Promotion window, show dialog you can't afford promotion
callClientFunction(player, "eventTalkJoined", playerCurrentRank, playerNextRank, false, true);
end
else
callClientFunction(player, "eventTalkJoined", playerCurrentRank, playerNextRank);
end
callClientFunction(player, "eventTalkJoinedOnly");
else
callClientFunction(player, "eventTalkExclusive");
end
callClientFunction(player, "eventTalkStepBreak");
player:endEvent();
end

View File

@@ -0,0 +1,510 @@
--[[
PopulaceCompanyShop Script
Functions:
eventTalkStepCantUse() -- When player tries to buy from another GC's shop
eventTalkPreJoin() -- Dialog for the shop
eventTalkPreJoinQuest() -- Tutorial dialog for the shop?
eventTalkJoined(???) -- Dialog for the shop, they salute. Orphaned parameter?
eventTalkFestival() -- Festival Day Event Dialog
eventTalkFestival2() -- Festival Day Event Follow-up Dialog
eventTalkMainMenu(???, ???) -- Shop menu for picking GC items
eventShopMenuOpen() -- Sets up shop menu. Calls getSpecialEventWork, value 8 shows GC firework & 11 a Patriot's Choker
eventShopMenuAsk() -- Opens up the shop menu.
eventShopMenuClose()
eventGuideChocoboWhistle(???) -- Tutorial dialog after purchasing Chocobo issuance slip. Orphaned parameter?
eventGuideTownTransport(index) -- Tutorial dialog after purchasing an aetherpass. Index is item ID.
eventAskChocoboCustomize(index, price) -- Chocobo Barding purchase dialog. Index is item ID.
eventChocoboCustomize() -- Follow-up dialog if you purchase Chocobo Barding.
getGrandCompanyNumber() -- Returns GC value of the NPC
getShopItemStartIndex(index) -- Gets starting index value based on GC shop
getShopItemEndIndex(index) -- Gets ending index value based on GC shop
getShopSellingItemMax(???) --
getShopSellingItemDetail(player, ???, ???)
eventTalkStepBreak() -- Returns NPC to their starting direction
--]]
require ("global")
require ("shop")
function init(npc)
return false, false, 0, 0;
end
gcOfficer = {
[1500202] = 1, -- Limsa Shop
[1500203] = 2, -- Grid Shop
[1500201] = 3, -- Flame Shop
}
shopInfo = { -- [index] = { itemID, itemQuality, itemQuantity, itemCost, gcRank, city, special, itemCategory }
[100001] = {3010403, 1, 10, 20, 0, 1, 0, 1},
[100002] = {3010402, 1, 10, 30, 0, 1, 0, 1},
[100003] = {3020202, 1, 1, 50, 0, 1, 0, 1},
[100004] = {3020406, 1, 20, 10, 0, 1, 0, 1},
[100005] = {3020403, 1, 10, 15, 0, 1, 0, 1},
[100006] = {3020402, 1, 5, 60, 0, 1, 0, 1},
[100007] = {3020404, 1, 5, 100, 0, 1, 0, 1},
[100008] = {3020528, 1, 5, 50, 0, 1, 0, 1},
[100009] = {3020516, 1, 5, 50, 0, 1, 0, 1},
[100010] = {3020411, 1, 1, 15, 0, 1, 0, 1},
[100011] = {3020412, 1, 1, 200, 0, 1, 0, 1},
[100012] = {3020509, 1, 1, 200, 0, 1, 0, 1},
[100013] = {3020510, 1, 1, 200, 0, 1, 0, 1},
[100014] = {10013001, 1, 20, 5, 0, 1, 0, 1},
[100015] = {10013002, 1, 20, 25, 0, 1, 0, 1},
[100016] = {10013003, 1, 20, 45, 0, 1, 0, 1},
[100017] = {10013004, 1, 20, 100, 0, 1, 0, 1},
[100018] = {10013005, 1, 20, 150, 0, 1, 0, 1},
[100019] = {3910402, 1, 99, 85, 0, 1, 0, 1},
[100020] = {3910103, 1, 99, 120, 0, 1, 0, 1},
[100021] = {3910203, 1, 99, 120, 0, 1, 0, 1},
[100022] = {3910305, 1, 99, 85, 0, 1, 0, 1},
[100023] = {3920004, 1, 999, 50, 0, 1, 0, 1},
[100024] = {3920006, 1, 999, 70, 0, 1, 0, 1},
[100025] = {3920003, 1, 999, 115, 0, 1, 0, 1},
[100026] = {3910005, 1, 99, 75, 0, 1, 0, 1},
[100027] = {3910006, 1, 99, 90, 0, 1, 0, 1},
[100028] = {3940011, 1, 20, 20, 0, 1, 0, 1},
[100029] = {3940010, 1, 20, 30, 0, 1, 0, 1},
[100030] = {3020504, 1, 1, 400, 15, 1, 0, 1},
[100031] = {3020505, 1, 1, 400, 15, 1, 0, 1},
[100032] = {3020506, 1, 1, 300, 31, 1, 0, 1},
[101001] = {4040010, 1, 1, 500, 0, 1, 0, 2},
[101002] = {4040110, 1, 1, 1000, 0, 1, 0, 2},
[101003] = {4040205, 1, 1, 1400, 0, 1, 0, 2},
[101004] = {4040305, 1, 1, 3000, 0, 1, 0, 2},
[101005] = {4040204, 1, 1, 4000, 0, 1, 0, 2},
[101006] = {4080304, 1, 1, 950, 0, 1, 0, 2},
[101007] = {4080211, 1, 1, 1000, 0, 1, 0, 2},
[101008] = {4080106, 1, 1, 2000, 0, 1, 0, 2},
[101009] = {4080303, 1, 1, 4000, 0, 1, 0, 2},
[101010] = {5020010, 1, 1, 900, 0, 1, 0, 2},
[101011] = {5020209, 1, 1, 1000, 0, 1, 0, 2},
[101012] = {5020213, 1, 1, 1600, 0, 1, 0, 2},
[101013] = {5020305, 1, 1, 4000, 0, 1, 0, 2},
[101014] = {8030350, 1, 1, 750, 0, 1, 0, 2},
[101015] = {8030447, 1, 1, 750, 0, 1, 0, 2},
[101016] = {8031223, 1, 1, 750, 0, 1, 0, 2},
[101017] = {8032008, 1, 1, 750, 0, 1, 0, 2},
[101018] = {9050029, 1, 1, 900, 0, 1, 0, 2},
[101019] = {9050044, 1, 1, 1900, 0, 1, 0, 2},
[101020] = {9040032, 1, 1, 950, 0, 1, 0, 2},
[101021] = {9040025, 1, 1, 1500, 0, 1, 0, 2},
[101022] = {8013201, 1, 1, 1000, 11, 1, 0, 2},
[101023] = {8032601, 1, 1, 1000, 11, 1, 0, 2},
[101024] = {8071301, 1, 1, 1000, 11, 1, 0, 2},
[101025] = {8081701, 1, 1, 1000, 11, 1, 0, 2},
[101026] = {8050620, 1, 1, 1200, 11, 1, 0, 2},
[101027] = {8050243, 1, 1, 1200, 11, 1, 0, 2},
[101028] = {8050344, 1, 1, 1200, 11, 1, 0, 2},
[101029] = {8050028, 1, 1, 1200, 11, 1, 0, 2},
[101030] = {8090706, 1, 1, 1200, 11, 1, 0, 2},
[101031] = {4030205, 1, 1, 2500, 13, 1, 0, 2},
[101032] = {4020306, 1, 1, 2500, 13, 1, 0, 2},
[101033] = {4040014, 1, 1, 2500, 13, 1, 0, 2},
[101034] = {4080408, 1, 1, 2500, 13, 1, 0, 2},
[101035] = {4070310, 1, 1, 2500, 13, 1, 0, 2},
[101036] = {5030307, 1, 1, 2500, 13, 1, 0, 2},
[101037] = {5020112, 1, 1, 2500, 13, 1, 0, 2},
[101038] = {4100205, 1, 1, 2000, 13, 1, 0, 2},
[101039] = {8011609, 1, 1, 3000, 15, 1, 0, 2},
[101040] = {8032311, 1, 1, 3000, 15, 1, 0, 2},
[101041] = {8071017, 1, 1, 3000, 15, 1, 0, 2},
[101042] = {8050132, 1, 1, 3000, 15, 1, 0, 2},
[101043] = {8081123, 1, 1, 3000, 15, 1, 0, 2},
[101044] = {4030117, 1, 1, 4500, 17, 1, 0, 2},
[101045] = {4020210, 1, 1, 4500, 17, 1, 0, 2},
[101046] = {4040406, 1, 1, 4500, 17, 1, 0, 2},
[101047] = {4080107, 1, 1, 4500, 17, 1, 0, 2},
[101048] = {4070108, 1, 1, 4500, 17, 1, 0, 2},
[101049] = {5030111, 1, 1, 4500, 17, 1, 0, 2},
[101050] = {5020013, 1, 1, 4500, 17, 1, 0, 2},
[101051] = {4100405, 1, 1, 4000, 17, 1, 0, 2},
[101052] = {8011610, 1, 1, 5000, 21, 1, 0, 2},
[101053] = {8032312, 1, 1, 5000, 21, 1, 0, 2},
[101054] = {8071018, 1, 1, 5000, 21, 1, 0, 2},
[101055] = {8050133, 1, 1, 5000, 21, 1, 0, 2},
[101056] = {8050769, 1, 1, 5000, 21, 1, 0, 2},
[101057] = {8081124, 1, 1, 5000, 21, 1, 0, 2},
[101058] = {8080565, 1, 1, 5000, 21, 1, 0, 2},
[101059] = {8090609, 1, 1, 5000, 21, 1, 0, 2},
[101060] = {9050021, 1, 1, 1000, 21, 1, 0, 2},
[101061] = {9050022, 1, 1, 1000, 21, 1, 0, 2},
[101062] = {9010025, 1, 1, 1000, 21, 1, 0, 2},
[101063] = {4100804, 1, 1, 5500, 23, 1, 0, 2},
[101064] = {8013614, 1, 1, 5500, 23, 1, 0, 2},
[101065] = {8032820, 1, 1, 5500, 23, 1, 0, 2},
[101066] = {8051516, 1, 1, 5500, 23, 1, 0, 2},
[101067] = {8071520, 1, 1, 5500, 23, 1, 0, 2},
[101068] = {9030060, 1, 1, 5500, 23, 1, 0, 2},
[101069] = {9050067, 1, 1, 5500, 23, 1, 0, 2},
[101070] = {8013615, 1, 1, 6000, 25, 1, 0, 2},
[101071] = {8013616, 1, 1, 6000, 25, 1, 0, 2},
[101072] = {8032821, 1, 1, 6000, 25, 1, 0, 2},
[101073] = {8071521, 1, 1, 6000, 25, 1, 0, 2},
[101074] = {8081914, 1, 1, 6000, 25, 1, 0, 2},
[101075] = {9040065, 1, 1, 6000, 25, 1, 0, 2},
[101076] = {9010061, 1, 1, 6000, 25, 1, 0, 2},
[101077] = {4100805, 1, 1, 6500, 27, 1, 0, 2},
[101078] = {4020408, 1, 1, 6500, 27, 1, 0, 2},
[101079] = {4040508, 1, 1, 6500, 27, 1, 0, 2},
[101080] = {4080508, 1, 1, 6500, 27, 1, 0, 2},
[101081] = {4070408, 1, 1, 6500, 27, 1, 0, 2},
[101082] = {5030408, 1, 1, 6500, 27, 1, 0, 2},
[101083] = {5020408, 1, 1, 6500, 27, 1, 0, 2},
[101084] = {4030604, 1, 1, 25000, 31, 1, 0, 2},
[101085] = {4020404, 1, 1, 25000, 31, 1, 0, 2},
[101086] = {4040504, 1, 1, 25000, 31, 1, 0, 2},
[101087] = {4080504, 1, 1, 25000, 31, 1, 0, 2},
[101088] = {4070404, 1, 1, 25000, 31, 1, 0, 2},
[101089] = {5030404, 1, 1, 25000, 31, 1, 0, 2},
[101090] = {5020404, 1, 1, 25000, 31, 1, 0, 2},
[101091] = {8013204, 1, 1, 6000, 31, 1, 0, 2},
[101092] = {8032604, 1, 1, 6000, 31, 1, 0, 2},
[101093] = {8071304, 1, 1, 6000, 31, 1, 0, 2},
[101094] = {8081704, 1, 1, 6000, 31, 1, 0, 2},
[102001] = {3020601, 1, 20, 5, 0, 1, 8, 3},
[102002] = {9040018, 1, 1, 1000, 11, 1, 11, 3},
[103001] = {2001004, 1, 1, 3000, 11, 1, 0, 4},
[103002] = {2001014, 1, 1, 3000, 15, 1, 0, 4},
[103003] = {2001017, 1, 1, 2000, 21, 1, 0, 4},
[103004] = {2001018, 1, 1, 3000, 21, 1, 0, 4},
[103005] = {2001019, 1, 1, 4000, 21, 1, 0, 4},
[103006] = {2001026, 1, 1, 25000, 27, 1, 0, 4},
[200001] = {3010403, 1, 10, 20, 0, 2, 0, 1},
[200002] = {3010402, 1, 10, 30, 0, 2, 0, 1},
[200003] = {3020203, 1, 1, 50, 0, 2, 0, 1},
[200004] = {3020406, 1, 20, 10, 0, 2, 0, 1},
[200005] = {3020403, 1, 10, 15, 0, 2, 0, 1},
[200006] = {3020402, 1, 5, 60, 0, 2, 0, 1},
[200007] = {3020404, 1, 5, 100, 0, 2, 0, 1},
[200008] = {3020528, 1, 5, 50, 0, 2, 0, 1},
[200009] = {3020516, 1, 5, 50, 0, 2, 0, 1},
[200010] = {3020411, 1, 1, 15, 0, 2, 0, 1},
[200011] = {3020412, 1, 1, 200, 0, 2, 0, 1},
[200012] = {3020509, 1, 1, 200, 0, 2, 0, 1},
[200013] = {3020510, 1, 1, 200, 0, 2, 0, 1},
[200014] = {10013001, 1, 20, 5, 0, 2, 0, 1},
[200015] = {10013002, 1, 20, 25, 0, 2, 0, 1},
[200016] = {10013003, 1, 20, 45, 0, 2, 0, 1},
[200017] = {10013004, 1, 20, 100, 0, 2, 0, 1},
[200018] = {10013005, 1, 20, 150, 0, 2, 0, 1},
[200019] = {3910402, 1, 99, 85, 0, 2, 0, 1},
[200020] = {3910103, 1, 99, 120, 0, 2, 0, 1},
[200021] = {3910203, 1, 99, 120, 0, 2, 0, 1},
[200022] = {3910305, 1, 99, 85, 0, 2, 0, 1},
[200023] = {3920004, 1, 999, 50, 0, 2, 0, 1},
[200024] = {3920006, 1, 999, 70, 0, 2, 0, 1},
[200025] = {3920003, 1, 999, 115, 0, 2, 0, 1},
[200026] = {3910005, 1, 99, 75, 0, 2, 0, 1},
[200027] = {3910006, 1, 99, 90, 0, 2, 0, 1},
[200028] = {3940011, 1, 20, 20, 0, 2, 0, 1},
[200029] = {3940010, 1, 20, 30, 0, 2, 0, 1},
[200030] = {3020504, 1, 1, 400, 15, 2, 0, 1},
[200031] = {3020505, 1, 1, 400, 15, 2, 0, 1},
[200032] = {3020506, 1, 1, 300, 31, 2, 0, 1},
[201001] = {5030107, 1, 1, 350, 0, 2, 0, 2},
[201002] = {5030207, 1, 1, 750, 0, 2, 0, 2},
[201003] = {5030206, 1, 1, 1000, 0, 2, 0, 2},
[201004] = {5030029, 1, 1, 1500, 0, 2, 0, 2},
[201005] = {5030031, 1, 1, 2400, 0, 2, 0, 2},
[201006] = {5030209, 1, 1, 3000, 0, 2, 0, 2},
[201007] = {5030028, 1, 1, 4000, 0, 2, 0, 2},
[201008] = {4020109, 1, 1, 800, 0, 2, 0, 2},
[201009] = {4020106, 1, 1, 1000, 0, 2, 0, 2},
[201010] = {4020008, 1, 1, 2200, 0, 2, 0, 2},
[201011] = {4020305, 1, 1, 4000, 0, 2, 0, 2},
[201012] = {4100005, 1, 1, 1000, 0, 2, 0, 2},
[201013] = {4100109, 1, 1, 4000, 0, 2, 0, 2},
[201014] = {8030035, 1, 1, 750, 0, 2, 0, 2},
[201015] = {8030919, 1, 1, 750, 0, 2, 0, 2},
[201016] = {8031821, 1, 1, 750, 0, 2, 0, 2},
[201017] = {8032220, 1, 1, 750, 0, 2, 0, 2},
[201018] = {9050029, 1, 1, 900, 0, 2, 0, 2},
[201019] = {9050044, 1, 1, 1900, 0, 2, 0, 2},
[201020] = {9040035, 1, 1, 950, 0, 2, 0, 2},
[201021] = {9040025, 1, 1, 1500, 0, 2, 0, 2},
[201022] = {8013202, 1, 1, 1000, 11, 2, 0, 2},
[201023] = {8032602, 1, 1, 1000, 11, 2, 0, 2},
[201024] = {8071302, 1, 1, 1000, 11, 2, 0, 2},
[201025] = {8081702, 1, 1, 1000, 11, 2, 0, 2},
[201026] = {8050148, 1, 1, 1200, 11, 2, 0, 2},
[201027] = {8050244, 1, 1, 1200, 11, 2, 0, 2},
[201028] = {8051222, 1, 1, 1200, 11, 2, 0, 2},
[201029] = {8050029, 1, 1, 1200, 11, 2, 0, 2},
[201030] = {8090707, 1, 1, 1200, 11, 2, 0, 2},
[201031] = {4030710, 1, 1, 2500, 13, 2, 0, 2},
[201032] = {4020211, 1, 1, 2500, 13, 2, 0, 2},
[201033] = {4040407, 1, 1, 2500, 13, 2, 0, 2},
[201034] = {4080213, 1, 1, 2500, 13, 2, 0, 2},
[201035] = {4070215, 1, 1, 2500, 13, 2, 0, 2},
[201036] = {5030113, 1, 1, 2500, 13, 2, 0, 2},
[201037] = {5020014, 1, 1, 2500, 13, 2, 0, 2},
[201038] = {4100608, 1, 1, 2000, 13, 2, 0, 2},
[201039] = {8010566, 1, 1, 3000, 15, 2, 0, 2},
[201040] = {8030625, 1, 1, 3000, 15, 2, 0, 2},
[201041] = {8070724, 1, 1, 3000, 15, 2, 0, 2},
[201042] = {8050618, 1, 1, 3000, 15, 2, 0, 2},
[201043] = {8080715, 1, 1, 3000, 15, 2, 0, 2},
[201044] = {4030016, 1, 1, 4500, 17, 2, 0, 2},
[201045] = {4020012, 1, 1, 4500, 17, 2, 0, 2},
[201046] = {4040111, 1, 1, 4500, 17, 2, 0, 2},
[201047] = {4080010, 1, 1, 4500, 17, 2, 0, 2},
[201048] = {4070013, 1, 1, 4500, 17, 2, 0, 2},
[201049] = {5030308, 1, 1, 4500, 17, 2, 0, 2},
[201050] = {5020113, 1, 1, 4500, 17, 2, 0, 2},
[201051] = {4100507, 1, 1, 4000, 17, 2, 0, 2},
[201052] = {8010567, 1, 1, 5000, 21, 2, 0, 2},
[201053] = {8030626, 1, 1, 5000, 21, 2, 0, 2},
[201054] = {8070725, 1, 1, 5000, 21, 2, 0, 2},
[201055] = {8050619, 1, 1, 5000, 21, 2, 0, 2},
[201056] = {8050768, 1, 1, 5000, 21, 2, 0, 2},
[201057] = {8080716, 1, 1, 5000, 21, 2, 0, 2},
[201058] = {8080564, 1, 1, 5000, 21, 2, 0, 2},
[201059] = {8090506, 1, 1, 5000, 21, 2, 0, 2},
[201060] = {9050025, 1, 1, 1000, 21, 2, 0, 2},
[201061] = {9050026, 1, 1, 1000, 21, 2, 0, 2},
[201062] = {9010025, 1, 1, 1000, 21, 2, 0, 2},
[201063] = {4100806, 1, 1, 5500, 23, 2, 0, 2},
[201064] = {8013617, 1, 1, 5500, 23, 2, 0, 2},
[201065] = {8032822, 1, 1, 5500, 23, 2, 0, 2},
[201066] = {8051517, 1, 1, 5500, 23, 2, 0, 2},
[201067] = {8071522, 1, 1, 5500, 23, 2, 0, 2},
[201068] = {9030061, 1, 1, 5500, 23, 2, 0, 2},
[201069] = {9050068, 1, 1, 5500, 23, 2, 0, 2},
[201070] = {8013618, 1, 1, 6000, 25, 2, 0, 2},
[201071] = {8013619, 1, 1, 6000, 25, 2, 0, 2},
[201072] = {8032823, 1, 1, 6000, 25, 2, 0, 2},
[201073] = {8071523, 1, 1, 6000, 25, 2, 0, 2},
[201074] = {8081915, 1, 1, 6000, 25, 2, 0, 2},
[201075] = {9040066, 1, 1, 6000, 25, 2, 0, 2},
[201076] = {9010062, 1, 1, 6000, 25, 2, 0, 2},
[201077] = {4100807, 1, 1, 6500, 27, 2, 0, 2},
[201078] = {4020409, 1, 1, 6500, 27, 2, 0, 2},
[201079] = {4040509, 1, 1, 6500, 27, 2, 0, 2},
[201080] = {4080509, 1, 1, 6500, 27, 2, 0, 2},
[201081] = {4070409, 1, 1, 6500, 27, 2, 0, 2},
[201082] = {5030409, 1, 1, 6500, 27, 2, 0, 2},
[201083] = {5020409, 1, 1, 6500, 27, 2, 0, 2},
[201084] = {4030605, 1, 1, 25000, 31, 2, 0, 2},
[201085] = {4020405, 1, 1, 25000, 31, 2, 0, 2},
[201086] = {4040505, 1, 1, 25000, 31, 2, 0, 2},
[201087] = {4080505, 1, 1, 25000, 31, 2, 0, 2},
[201088] = {4070405, 1, 1, 25000, 31, 2, 0, 2},
[201089] = {5030405, 1, 1, 25000, 31, 2, 0, 2},
[201090] = {5020405, 1, 1, 25000, 31, 2, 0, 2},
[201091] = {8013205, 1, 1, 6000, 31, 2, 0, 2},
[201092] = {8032605, 1, 1, 6000, 31, 2, 0, 2},
[201093] = {8071305, 1, 1, 6000, 31, 2, 0, 2},
[201094] = {8081705, 1, 1, 6000, 31, 2, 0, 2},
[202001] = {3020603, 1, 20, 5, 0, 2, 8, 3},
[202002] = {9040018, 1, 1, 1000, 11, 2, 11, 3},
[203001] = {2001005, 1, 1, 3000, 11, 2, 0, 4},
[203002] = {2001015, 1, 1, 3000, 15, 2, 0, 4},
[203003] = {2001020, 1, 1, 2000, 21, 2, 0, 4},
[203004] = {2001021, 1, 1, 3000, 21, 2, 0, 4},
[203005] = {2001022, 1, 1, 4000, 21, 2, 0, 4},
[203006] = {2001026, 1, 1, 25000, 27, 2, 0, 4},
[300001] = {3010403, 1, 10, 20, 0, 3, 0, 1},
[300002] = {3010402, 1, 10, 30, 0, 3, 0, 1},
[300003] = {3020204, 1, 1, 50, 0, 3, 0, 1},
[300004] = {3020406, 1, 20, 10, 0, 3, 0, 1},
[300005] = {3020403, 1, 10, 15, 0, 3, 0, 1},
[300006] = {3020402, 1, 5, 60, 0, 3, 0, 1},
[300007] = {3020404, 1, 5, 100, 0, 3, 0, 1},
[300008] = {3020528, 1, 5, 50, 0, 3, 0, 1},
[300009] = {3020516, 1, 5, 50, 0, 3, 0, 1},
[300010] = {3020411, 1, 1, 15, 0, 3, 0, 1},
[300011] = {3020412, 1, 1, 200, 0, 3, 0, 1},
[300012] = {3020509, 1, 1, 200, 0, 3, 0, 1},
[300013] = {3020510, 1, 1, 200, 0, 3, 0, 1},
[300014] = {10013001, 1, 20, 5, 0, 3, 0, 1},
[300015] = {10013002, 1, 20, 25, 0, 3, 0, 1},
[300016] = {10013003, 1, 20, 45, 0, 3, 0, 1},
[300017] = {10013004, 1, 20, 100, 0, 3, 0, 1},
[300018] = {10013005, 1, 20, 150, 0, 3, 0, 1},
[300019] = {3910402, 1, 99, 85, 0, 3, 0, 1},
[300020] = {3910103, 1, 99, 120, 0, 3, 0, 1},
[300021] = {3910203, 1, 99, 120, 0, 3, 0, 1},
[300022] = {3910305, 1, 99, 85, 0, 3, 0, 1},
[300023] = {3920004, 1, 999, 50, 0, 3, 0, 1},
[300024] = {3920006, 1, 999, 70, 0, 3, 0, 1},
[300025] = {3920003, 1, 999, 115, 0, 3, 0, 1},
[300026] = {3910005, 1, 99, 75, 0, 3, 0, 1},
[300027] = {3910006, 1, 99, 90, 0, 3, 0, 1},
[300028] = {3940011, 1, 20, 20, 0, 3, 0, 1},
[300029] = {3940010, 1, 20, 30, 0, 3, 0, 1},
[300030] = {3020504, 1, 1, 400, 15, 3, 0, 1},
[300031] = {3020505, 1, 1, 400, 15, 3, 0, 1},
[300032] = {3020506, 1, 1, 300, 31, 3, 0, 1},
[301001] = {4030006, 1, 1, 400, 0, 3, 0, 2},
[301002] = {4030015, 1, 1, 1000, 0, 3, 0, 2},
[301003] = {4030405, 1, 1, 1600, 0, 3, 0, 2},
[301004] = {4030506, 1, 1, 3200, 0, 3, 0, 2},
[301005] = {4030505, 1, 1, 4000, 0, 3, 0, 2},
[301006] = {4070011, 1, 1, 550, 0, 3, 0, 2},
[301007] = {4070105, 1, 1, 1000, 0, 3, 0, 2},
[301008] = {4070212, 1, 1, 1500, 0, 3, 0, 2},
[301009] = {4070211, 1, 1, 4000, 0, 3, 0, 2},
[301010] = {4100710, 1, 1, 450, 0, 3, 0, 2},
[301011] = {4100403, 1, 1, 1000, 0, 3, 0, 2},
[301012] = {4100404, 1, 1, 1900, 0, 3, 0, 2},
[301013] = {4100306, 1, 1, 4000, 0, 3, 0, 2},
[301014] = {8030248, 1, 1, 750, 0, 3, 0, 2},
[301015] = {8030548, 1, 1, 750, 0, 3, 0, 2},
[301016] = {8031021, 1, 1, 750, 0, 3, 0, 2},
[301017] = {8031513, 1, 1, 750, 0, 3, 0, 2},
[301018] = {9050029, 1, 1, 900, 0, 3, 0, 2},
[301019] = {9050044, 1, 1, 1900, 0, 3, 0, 2},
[301020] = {9040036, 1, 1, 950, 0, 3, 0, 2},
[301021] = {9040025, 1, 1, 1500, 0, 3, 0, 2},
[301022] = {8013203, 1, 1, 1000, 11, 3, 0, 2},
[301023] = {8032603, 1, 1, 1000, 11, 3, 0, 2},
[301024] = {8071303, 1, 1, 1000, 11, 3, 0, 2},
[301025] = {8081703, 1, 1, 1000, 11, 3, 0, 2},
[301026] = {8050520, 1, 1, 1200, 11, 3, 0, 2},
[301027] = {8051024, 1, 1, 1200, 11, 3, 0, 2},
[301028] = {8050345, 1, 1, 1200, 11, 3, 0, 2},
[301029] = {8050449, 1, 1, 1200, 11, 3, 0, 2},
[301030] = {8090708, 1, 1, 1200, 11, 3, 0, 2},
[301031] = {4030305, 1, 1, 2500, 13, 3, 0, 2},
[301032] = {4020011, 1, 1, 2500, 13, 3, 0, 2},
[301033] = {4040208, 1, 1, 2500, 13, 3, 0, 2},
[301034] = {4080306, 1, 1, 2500, 13, 3, 0, 2},
[301035] = {4070012, 1, 1, 2500, 13, 3, 0, 2},
[301036] = {5030037, 1, 1, 2500, 13, 3, 0, 2},
[301037] = {5020217, 1, 1, 2500, 13, 3, 0, 2},
[301038] = {4100112, 1, 1, 2000, 13, 3, 0, 2},
[301039] = {8011522, 1, 1, 3000, 15, 3, 0, 2},
[301040] = {8030744, 1, 1, 3000, 15, 3, 0, 2},
[301041] = {8070361, 1, 1, 3000, 15, 3, 0, 2},
[301042] = {8050766, 1, 1, 3000, 15, 3, 0, 2},
[301043] = {8080562, 1, 1, 3000, 15, 3, 0, 2},
[301044] = {4030408, 1, 1, 4500, 17, 3, 0, 2},
[301045] = {4020113, 1, 1, 4500, 17, 3, 0, 2},
[301046] = {4040306, 1, 1, 4500, 17, 3, 0, 2},
[301047] = {4080409, 1, 1, 4500, 17, 3, 0, 2},
[301048] = {4070311, 1, 1, 4500, 17, 3, 0, 2},
[301049] = {5030210, 1, 1, 4500, 17, 3, 0, 2},
[301050] = {5020307, 1, 1, 4500, 17, 3, 0, 2},
[301051] = {4100712, 1, 1, 4000, 17, 3, 0, 2},
[301052] = {8011523, 1, 1, 5000, 21, 3, 0, 2},
[301053] = {8030745, 1, 1, 5000, 21, 3, 0, 2},
[301054] = {8070362, 1, 1, 5000, 21, 3, 0, 2},
[301055] = {8050811, 1, 1, 5000, 21, 3, 0, 2},
[301056] = {8050767, 1, 1, 5000, 21, 3, 0, 2},
[301057] = {8080015, 1, 1, 5000, 21, 3, 0, 2},
[301058] = {8080563, 1, 1, 5000, 21, 3, 0, 2},
[301059] = {8090709, 1, 1, 5000, 21, 3, 0, 2},
[301060] = {9050023, 1, 1, 1000, 21, 3, 0, 2},
[301061] = {9050024, 1, 1, 1000, 21, 3, 0, 2},
[301062] = {9010025, 1, 1, 1000, 21, 3, 0, 2},
[301063] = {4100808, 1, 1, 5500, 23, 3, 0, 2},
[301064] = {8013620, 1, 1, 5500, 23, 3, 0, 2},
[301065] = {8032824, 1, 1, 5500, 23, 3, 0, 2},
[301066] = {8051518, 1, 1, 5500, 23, 3, 0, 2},
[301067] = {8071524, 1, 1, 5500, 23, 3, 0, 2},
[301068] = {9030062, 1, 1, 5500, 23, 3, 0, 2},
[301069] = {9050069, 1, 1, 5500, 23, 3, 0, 2},
[301070] = {8013621, 1, 1, 6000, 25, 3, 0, 2},
[301071] = {8013622, 1, 1, 6000, 25, 3, 0, 2},
[301072] = {8032825, 1, 1, 6000, 25, 3, 0, 2},
[301073] = {8071525, 1, 1, 6000, 25, 3, 0, 2},
[301074] = {8081916, 1, 1, 6000, 25, 3, 0, 2},
[301075] = {9040067, 1, 1, 6000, 25, 3, 0, 2},
[301076] = {9010063, 1, 1, 6000, 25, 3, 0, 2},
[301077] = {4100809, 1, 1, 6500, 27, 3, 0, 2},
[301078] = {4020410, 1, 1, 6500, 27, 3, 0, 2},
[301079] = {4040510, 1, 1, 6500, 27, 3, 0, 2},
[301080] = {4080510, 1, 1, 6500, 27, 3, 0, 2},
[301081] = {4070410, 1, 1, 6500, 27, 3, 0, 2},
[301082] = {5030410, 1, 1, 6500, 27, 3, 0, 2},
[301083] = {5020410, 1, 1, 6500, 27, 3, 0, 2},
[301084] = {4030606, 1, 1, 25000, 31, 3, 0, 2},
[301085] = {4020406, 1, 1, 25000, 31, 3, 0, 2},
[301086] = {4040506, 1, 1, 25000, 31, 3, 0, 2},
[301087] = {4080506, 1, 1, 25000, 31, 3, 0, 2},
[301088] = {4070406, 1, 1, 25000, 31, 3, 0, 2},
[301089] = {5030406, 1, 1, 25000, 31, 3, 0, 2},
[301090] = {5020406, 1, 1, 25000, 31, 3, 0, 2},
[301091] = {8013206, 1, 1, 6000, 31, 3, 0, 2},
[301092] = {8032606, 1, 1, 6000, 31, 3, 0, 2},
[301093] = {8071306, 1, 1, 6000, 31, 3, 0, 2},
[301094] = {8081706, 1, 1, 6000, 31, 3, 0, 2},
[302001] = {3020602, 1, 20, 5, 0, 3, 8, 3},
[302002] = {9040018, 1, 1, 1000, 11, 3, 11, 3},
[303001] = {2001006, 1, 1, 3000, 11, 3, 0, 4},
[303002] = {2001016, 1, 1, 3000, 15, 3, 0, 4},
[303003] = {2001023, 1, 1, 2000, 21, 3, 0, 4},
[303004] = {2001024, 1, 1, 3000, 21, 3, 0, 4},
[303005] = {2001025, 1, 1, 4000, 21, 3, 0, 4},
[303006] = {2001026, 1, 1, 25000, 27, 3, 0, 4},
}
function onEventStarted(player, npc, triggerName)
skipGCcheck = 0; -- 0 No, 1 Yes
playerGC = player.gcCurrent;
playerGCSeal = 1000200 + playerGC;
playerCurrentRank = 13;
npcId = npc:GetActorClassId();
if (playerGC == gcOfficer[npcId] or skipGCcheck == 1) then
callClientFunction(player, "eventTalkPreJoin");
--player:SendMessage(0x20, "", "[Info]: Client takes awhile to load GC shops");
while (true) do
eventTalkChoice = callClientFunction(player, "eventTalkMainMenu", 8, 11);
--player:SendMessage(0x20, "", "eventTalkMainMenu: " .. tostring(eventTalkChoice));
if (eventTalkChoice == 1) then
t1, t2, t3 = callClientFunction(player, "eventShopMenuOpen");
--player:SendMessage(0x20, "", "eventShopMenuOpen: " .. tostring(t1) .. ", ".. tostring(t2) .. ", ".. tostring(t3));
while (true) do
-- TODO: ADD RANK CHECK, CITY CHECK, AND ITEM-RANGE CHECK
buyResult, buyIndex = callClientFunction(player, "eventShopMenuAsk");
if (buyIndex == -1) then
callClientFunction(player, "eventShopMenuClose");
break;
else
-- [index] = { itemID, itemQuality, itemQuantity, itemCost gcRank, city, special, itemCategory }
if (shopInfo[buyIndex][8] == 4) then
location = INVENTORY_KEYITEMS;
else
location = INVENTORY_NORMAL;
end
end
purchaseItem(player, location, shopInfo[buyIndex][1], shopInfo[buyIndex][3], shopInfo[buyIndex][2], shopInfo[buyIndex][4], playerGCSeal);
end
--player:SendMessage(0x20, "", "Player picked an item at gcSealShopIndex " .. tostring(buyResult) .. ", ".. tostring(buyIndex));
elseif (eventTalkChoice == -1) then
break;
end
end
else
callClientFunction(player, "eventTalkStepCantUse");
end
callClientFunction(player, "eventTalkStepBreak");
player:endEvent();
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:GetItemPackage(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

@@ -0,0 +1,131 @@
--[[
PopulaceCompanyWarp Script
Functions:
eventTalkWelcome(player) - Start Text
eventAskMainMenu(player, index) - Shows teleport menu, hides the teleport location at index value to prevent warping to the spot you're at
eventAfterWarpOtherZone(player) - Fades out for warp
eventTalkStepBreak() - Holds the client up for whatever reason?
--]]
require ("global")
warpNpc =
{ --[actorId] = {warpIndex, cityId} -- ()s around name indicate missing NPC + Aethernet
[1500321] = {1, 1}, -- (Storm Private Gardner)
[1500331] = {2, 1}, -- (Storm Private Rich)
[1500323] = {3, 1}, -- (Storm Private Potter)
[1500330] = {4, 1}, -- (Storm Private Hunt)
[1500322] = {5, 1}, -- (Storm Private Abel)
[1500332] = {6, 1}, -- (Storm Private Stone)
[1500339] = {7, 1}, -- (Storm Private Holt)
[1500324] = {1, 2}, -- serpent_private_white
[1500334] = {2, 2}, -- serpent_private_hill
[1500326] = {3, 2}, -- serpent_private_carver
[1500333] = {4, 2}, -- serpent_private_stone
[1500325] = {5, 2}, -- serpent_private_holmes
[1500335] = {6, 2}, -- serpent_private_kirk
[1500327] = {1, 3}, -- flame_private_newton
[1500337] = {2, 3}, -- (Flame Private Tanner)
[1500329] = {3, 3}, -- (Flame Private Morning)
[1500336] = {4, 3}, -- (Flame Private Covey)
[1500328] = {5, 3}, -- flame_private_allen
[1500338] = {6, 3}, -- (Flame Private Yar)
}
aethernet =
{
{ -- 1: Limsa
{zone = 230, x = -424.140, y = 42.000, z = 371.988, r = -2.472}, -- 1 - Aetheryte Plaza
{zone = 133, x = -439.744, y = 40.000, z = 234.376, r = 0.287}, -- 2 - Drowning Wench
{zone = 230, x = -498.131, y = 43.622, z = 60.818, r = 0.254}, -- 3 - The Bismarck
{zone = 230, x = -759.331, y = 12.000, z = 239.413, r = -0.869}, -- 4 - Ferry Docks
{zone = 230, x = -623.582, y = 4.000, z = 369.318, r = 1.736}, -- 5 - Fisherman's Bottom
{zone = 230, x = -525.536, y = 18.000, z = 173.735, r = 3.082}, -- 6 - The Octant
{zone = 133, x = -231.711, y = 12.000, z = 193.573, r = -0.786}, -- 7 - Procession of Terns
{zone = 128, x = -20.783, y = 42.214, z = 146.946, r = 2.046}, -- 8 - Zephyr Gate
},
{ -- 2: Gridania
{zone = 206, x = -107.878, y = 17.524, z = -1343.871, r = 0.657}, -- 1 - Aetheryte Plaza
{zone = 155, x = 96.868, y = 3.480, z = -1211.040, r = 2.582}, -- 2 - Carline Canopy
{zone = 206, x = 86.942, y = 19.789, z = -1420.891, r = 2.965}, -- 3 - Atelier Fen-Yil
{zone = 206, x = -84.621, y = 19.061, z = -1502.665, r = 0.756}, -- 4 - Whistling Miller
{zone = 206, x = 205.101, y = 9.526, z = -1245.405, r = -1.749}, -- 5 - Quiver's Hold
{zone = 206, x = 160.578, y = 25.061, z = -1556.662, r = 1.896}, -- 6 - Wailing Barracks
{zone = 150, x = 318.838, y = 4.036, z = -992.071, r = -0.307}, -- 7 - Mistalle Bridges
{zone = 206, x = -192.167, y = 4.466, z = -1061.777, r = -0.026}, -- 8 - Berlends Bridges
},
{ -- 3: Ul'dah
{zone = 175, x = -190.574, y = 190.000, z = 18.086, r = 2.190}, -- 1 - Aetheryte Plaza
{zone = 175, x = -36.513, y = 192.000, z = 37.130, r = -0.490}, -- 2 - Quicksand
{zone = 209, x = -192.971, y = 230.000, z = 209.348, r = 2.860}, -- 3 - Frondale's Phrontistery
{zone = 209, x = -60.243, y = 200.000, z = 257.718, r = -1.276}, -- 4 - Onyx Lane
{zone = 209, x = -147.633, y = 198.000, z = 160.064, r = -1.600}, -- 5 - Gold Court
{zone = 209, x = -263.776, y = 202.000, z = 206.699, r = -3.135}, -- 6 - Arrzaneth Ossuary
{zone = 170, x = -29.721, y = 182.635, z = -76.313, r = 2.625}, -- 7 - Gate of Nald
{zone = 170, x = 129.957, y = 183.862, z = 220.719, r = 1.515}, -- 8 - Gate of Thal
}
}
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local passLimsa = 2001014;
local passGrid = 2001015;
local passUldah = 2001016;
passCheck = 1; -- 0 = Check player for Aetherpass keyitem. 1 = Ignore it.
npcId = npc:GetActorClassId();
city = warpNpc[npcId][2];
if (city == 1) then
if player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(passLimsa) then
passCheck = 1;
else
if (passCheck == 0) then callClientFunction(player, "eventTalkWelcome", player); end
end;
elseif (city == 2) then
-- if player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(passGrid) then
passCheck = 1;
-- else
-- if passCheck == 0 then callClientFunction(player, "eventTalkWelcome", player); end
--end;
elseif (city == 3) then
if (player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(passUldah)) then
passCheck = 1;
else
if (passCheck == 0) then callClientFunction(player, "eventTalkWelcome", player); end
end
end
if (passCheck == 1) then
choice = callClientFunction(player, "eventAskMainMenu", player, warpNpc[npcId][1]);
if (choice ~= 0) then
callClientFunction(player, "eventAfterWarpOtherZone", player);
wait(1);
player:EndEvent();
local player_zone = player:GetPos()[5];
spawnType = 0x0A;
if (player_zone == aethernet[city][choice].zone) then
GetWorldManager():DoPlayerMoveInZone(player, aethernet[city][choice].x, aethernet[city][choice].y, aethernet[city][choice].z, aethernet[city][choice].r, spawnType);
else
GetWorldManager():DoZoneChange(player, aethernet[city][choice].zone, nil, 0, spawnType, aethernet[city][choice].x, aethernet[city][choice].y, aethernet[city][choice].z, aethernet[city][choice].r);
end;
else
player:EndEvent();
end
end
end

View File

@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0;
end

View File

@@ -0,0 +1,68 @@
--[[
PopulaceFlyingShip Script
Functions:
eventIn(player, hasTicket, nil?, travelPrice) - If hasTicket == nil, say no money text.
eventOut(isAborting) - Set isAborting to 30010 if player didn't "use" the airship. Shows no refund warning.
eventNG(player) - Message said when player is talking to the wrong npc.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
-- Special case for A Slippery Stone and Cutthroat Prices
if (player:HasQuest(110737) == true) then
require ("quests/etc/etc3g3");
local quest = player:GetQuest("Etc3g3");
if (quest:GetSequence() == SEQ_000) then
local choice = callClientFunction(player, "delegateEvent", player, quest, "processEvent_005");
if (choice == 1) then
quest:StartSequence(SEQ_001);
addPlayerToAirship(player, 2);
end
player:EndEvent();
return;
end
elseif (player:HasQuest(110728) == true) then
require ("quests/etc/etc3u3");
local quest = player:GetQuest("Etc3u3");
if (quest:GetSequence() == SEQ_000) then
local choice = callClientFunction(player, "delegateEvent", player, quest, "processEvent_005");
if (choice == 1) then
quest:StartSequence(SEQ_001);
addPlayerToAirship(player, 3);
end
player:EndEvent();
return;
end
end
-- Otherwise normal operation
callClientFunction(player, "eventIn", player, false, nil, 5);
player:EndEvent();
end
function addPlayerToAirship(player, city)
if (city == 1) then
-- Limsa Airship
GetWorldManager():WarpToPosition(player, -764.519, -3.146, 384.154, 1.575);
--GetWorldManager():AddPlayerToShipList(player, 2);
elseif (city == 2) then
-- Gridania Airship
GetWorldManager():WarpToPosition(player, 54.47, -7, -1198.54, -0.02);
--GetWorldManager():AddPlayerToShipList(player, 3);
elseif (city == 3) then
-- Ul'dah Airship
GetWorldManager():WarpToPosition(player, -126.580, 271.2, 156.435, -1.35);
--GetWorldManager():AddPlayerToShipList(player, 4);
end
end

View File

@@ -0,0 +1,95 @@
--[[
PopulaceGuildlevePublisher Script
Functions:
eventTalkType(level (changes factionLeves), sayIntro, brokenBladePoints, shieldsPoints, hornhandPoints, showTutorialLeves, doOmen (!=0), menuId (to Jump), leveAllowances, ?, ?, ?)
eventTalkPack(startGuildlevePack, endGuildlevePack)
eventTalkCard(card1,card2,card3,card4,card5,card6,card7,card8)
eventTalkDetail(guildLeveId, factionEvaluating, rewardType1, rewardQuantity1, rewardType2, rewardQuantity2, boostPoint, previouslyCompleted, completionBonus)
eventTalkAfterOffer()
eventHistoryleveExist(guildLeveId)
eventHistoryleveCannot()
eventGLChangeDetail(?, guildLeveId, boostPoint, rewardType1, rewardQuantity1, rewardType2, rewardQuantity2, factionEvaluating, previouslyCompleted)
eventTalkChangeOne(skipQuestion)
talkOfferMaxOver()
askRetryRegionalleve(guildLeveId, leveAllowances);
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc)
::MENU_LOOP::
menuChoice = callClientFunction(player, "eventTalkType", 0x30, true, 0x02CE, 0x356, 0x367, true, 0, nil, 0x29, 0,0,0);
--Battlecraft
if (menuChoice == 1) then
resultGLPack = callClientFunction(player, "eventTalkPack", 201, 207);
if (resultGLPack == nil) then
goto MENU_LOOP;
else
::CARDS_LOOP::
cards = {0x30C3, 0x30C4, 0x30C1, 0x30C5, 0x30C6, 0x30C7, 0x30C8, 0x30C9};
chosenGLCard = callClientFunction(player, "eventTalkCard", cards[1], cards[2], cards[3], cards[4], cards[5], cards[6], cards[7], cards[8]);
if (chosenGLCard == -1) then
goto MENU_LOOP;
else
wasAccepted = callClientFunction(player, "eventTalkDetail", cards[chosenGLCard], 0, 0xF4242, 0xD, 0xF4242, 0, 0, true, 0);
if (wasAccepted == true) then
end
goto CARDS_LOOP;
end
end
--FieldCraft Miner
elseif (menuChoice == 0x15) then
--FieldCraft Botanist
elseif (menuChoice == 0x16) then
--FieldCraft Fisher
elseif (menuChoice == 0x17) then
--FieldCraft Quit
elseif (menuChoice == 0x18) then
--Faction Broken Blade
elseif (menuChoice == 0x29) then
--Faction Shields
elseif (menuChoice == 0x2A) then
--Faction Horn and Hand
elseif (menuChoice == 0x2B) then
--Leve Evaluation
elseif (menuChoice == 5) then
--Tutorial
elseif (menuChoice == 6) then
--End of Info
elseif (menuChoice == 7) then
--Quit
elseif (menuChoice == 8) then
end
--
--
--
player:EndEvent();
end
function onEventUpdate(player, npc, step, menuOptionSelected)
--player:RunEventFunction("eventTalkType", 0x32, true, 0x02CE, 0x356, 0x367, false, 2, nil, 0x29, 0,0,0);
player:RunEventFunction("eventTalkPack", 201, 207);
--player:RunEventFunction("eventTalkCard", 0x30C3, 0x30C4, 0x30C1, 0x30C5, 0x30C6, 0x30C7, 0x30C8, 0x30C9);
--
--player:RunEventFunction("eventGLChangeDetail", 0xDEAD, 0x30C4, 0xFF, 0xF4242, 0xD, 0xF4242, 0, 2, true);
end

View File

@@ -0,0 +1,51 @@
--[[
PopulaceItemRepairer Script
Functions:
talkWelcome(player, sayWelcomeText, currentLevel?, changes 1500243 from "welcome" to "well met") - Opens the main menu
selectItem(nil, pageNumber, ?, condition1, condition2, condition3, condition4, condition5) - Select item slot.
confirmRepairItem(player, price, itemId, hq grade) - Shows the confirm box for item repair.
confirmUseFacility(player, price) - Shows confirm box for using facility. Default price is 11k?
finishTalkTurn() - Call at end to stop npc from staring at the player (eeeek)
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
result = callClientFunction(player, "talkWelcome", player, true, 20, false);
if (result == 1) then
local currentPage = 1;
local slotToRepair = nil;
while (true) do
slot, page, listIndx = callClientFunction(player, "selectItem", nil, currentPage, 4, 2, 55, 55, 55, 55);
if (slot == nil and page ~= nil) then
currentPage = page;
else
slotToRepair = slot;
break;
end
end
if (slotToRepair ~= nil) then
callClientFunction(player, "confirmRepairItem", player, 100, 8032827, 0);
end
elseif (result == 2) then
callClientFunction(player, "confirmUseFacility", player);
end
callClientFunction(player, "finishTalkTurn");
player:EndEvent();
end

View File

@@ -0,0 +1,72 @@
--[[
PopulaceLinkshellManager Script
Functions:
eventTalkStep1(noLinkshellActive) - Says intro. If noLinkshellActive = true, say newbie stuff.
eventTalkStep2(noLinkshellActive) - Shows menu, if noLinkshellActive = true, only give ability to make linkshell.
eventTalkStepMakeupDone() - Confirm when creating LS
eventTalkStepModifyDone() - Confirm when modding LS
eventTalkStepBreakDone() - Confirm when deleting LS
Text IDs:
25121 - That [@SWITCH($E8(1),linkshell,company)] name is already being used.
25122 - That [@SWITCH($E8(1),linkshell,company)] name cannot be used.
25123 - The [@SWITCH($E8(1),linkshell,company)] “[@STRING($EA(2))]” has been [@SWITCH($E8(1),created,founded)].
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function createLinkshell(player, name, crest)
GetWorldManager():RequestWorldLinkshellCreate(player, name, crest);
return waitForSignal("ls_result");
end
function modifyLinkshell(player, name, crest)
end
function disbandLinkshell(player, name, crest)
end
function onEventStarted(player, npc, triggerName)
local hasNoActiveLS = false;
callClientFunction(player, "eventTalkStep1", hasNoActiveLS);
local command, lsName, crestId = callClientFunction(player, "eventTalkStep2", hasNoActiveLS);
--Create
if (command == 3) then
local result = createLinkshell(player, lsName, crestId);
if (result == 0) then
callClientFunction(player, "eventTalkStepMakeupDone");
elseif (result == 1) then
player:SendGameMessage(player, GetWorldMaster(), 25121, 0x20); --LS already exists
callClientFunction(player, "eventTalkStepBreakDone");
elseif (result == 2) then
player:SendGameMessage(player, GetWorldMaster(), 25122, 0x20); --Cannot use this name (reserved/banned)
callClientFunction(player, "eventTalkStepBreakDone");
elseif (result == 3) then
end
--Modify
elseif (command == 4) then
modifyLinkshell(player, lsName, crestId);
callClientFunction(player, "eventTalkStepModifyDone");
--Disband
elseif (command == 5) then
disbandLinkshell(player, lsName, crestId);
callClientFunction(player, "eventTalkStepBreakDone");
end
player:endEvent();
end

View File

@@ -0,0 +1,24 @@
--[[
PopulaceNMReward Script
Functions:
eventTalkStep0(player, ?, ?) - Opens the main menu
eventTalkStep0_1(player) - "Ain't running a charity here", message said when you have insufficent funds
eventTalkStep0_2(player, hasItems) - Relic Quest dialog.
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
callClientFunction(player, "eventTalkStep0", player, 0);
player:EndEvent();
end

View File

@@ -0,0 +1,381 @@
--[[
PopulacePassiveGLPublisher
Operates the Local Levequest selection menus.
Functions:
askOfferPack(player)
Desc: Show class selection menu.
Params: * player - The player actor.
Returns: Value dictating which item on the list was selected (1-8 for class, nil if exited/canceled)
askOfferRank(player)
Desc: Show Level selection menu.
Params: * player - The player actor.
Returns: Value dictating which item on the list was selected (1 = Lv01, 2 = Lv20, 3 = Lv40, nil if exited/canceled)
askOfferQuest(player, ?, questId1, questId2, questId3, questId4, questId5, questId6, questId7, questId8)
Desc: Show Leve quest selection menu with up to 8 questId entries
Params: * player - The player actor.
* ? - Unused param. Capture has a 2.
* questId 1-8 - The local levequests available up to 8 quests.
Returns: 1 through 8 for an accepted leve in the order sent, -1 for hitting "Return", and Nil for "Cancel"
confirmOffer(player, questId)
Desc: Opens prompt asking whether to activate the leve and begin it.
Params: * player - The player actor.
* questId - The quest being confirmed.
Returns: Boolean - True on Yes, false on No or hitting escape.
confirmMaxOffer(player)
Desc: Opens ask widget stating you'll be capped on leves after accepting.
Params: * player - The player actor. Unused.
Returns: Boolean - True on Accept, false on "Quit" or hitting escape.
talkOfferWelcome(player, numAllowance)
Desc: NPC intro dialog as well as stating your available leve allowances.
Params: * player - The player actor.
* numAllowance - The number of leve allowances the player still has.
talkOfferDecide()
Desc: Makes the NPC say dialog following the acceptance of a leve.
Params: None
talkOfferMaxOver()
Desc: Makes the NPC say dialog stating the player is carrying too many leves currently.
Params: None
finishTalkTurn()
Desc: Ends the npc actor's turn towards you. Call this at the end of the script or the
npc will be stuck "facing" the player.
Params: None
selectDiscardGuildleve()
Desc: Opens the Journal widget to select a leve to discard. This is a follow-up to askDiscardGuildleve().
Params: None
Returns: Quest Actor
confirmJournal(questId, difficulty, unused, itemsCompleted, remainingMats, hasMaterials, unused)
Desc: Opens askJournalDetailWidget displaying current status of the leve.
Params: * questId - The current quest being confirmed.
* difficulty - The difficulty of the quest.
* unused - Unused param.
* itemsComplete - Sets the number of items crafted.
* remainingMats - Sets the remaining materials.
* hasMaterials - If set to 1, shows the progress section.
* unused - While loaded into widget, it doesn't do anything with this journalType (13).
Returns: True on "Exchange", Nil on "Return" or hitting Escape key
askDiscardGuildleve()
Desc: Opens an ask widget, stating the player cannot accept any more guildleves and if they'd want to return one to make room.
Params: None
Returns: Boolean
confirmDiscardGuildleve(?, questId, guildleveId)
Desc: Opens an ask widget, confirming the returning of the selected guildleve.
Params: * ? - Most likely a player actor, but unused.
* questId - The dialog is "Returning <quest>. Are you certain?". This is the questId being returned.
* guildleveId - This is mostly unused, Japanese localization has a weird switch to use this. Can be nil.
Returns: Boolean
askRetryRegionalleve(questId, numAllowance)
Desc: Opens an ask widget to re-attempt leve questId while showing leveAllowances. If no is selected, a second widget appears to confirm abandoning it.
Params: * questId - The questId being retried.
* numAllowance - The number of leve allowances the player still has.
Returns: Menu1 - Is 1 if yes is selected, 2 if no. Nil if Escape is hit (resend function in this case?)
Menu2 - Is 1 if yes is selected (leve abandoned), 2 if no. Nil if Menu1 isn't set to 2
Notes:
50141 - You have <num> leve allowances remaining.
50142 - You have run out of leve allowances. You cannot accept any more levequests at this time.
50143 - You cannot accept any more levequests at this time.
Local Leves:
~~Limsa~~
CRP: Baderon's New Counter (120007)
The Mad Fisher (120017)
Building Bridges (120039)
High Stakes (120047)
Training and Trees (120061)
BSM: Baderon's New Sword (120005)
Got Ingots (120013)
Ship Shape (120014)
A Want of Weapons (120015)
Skull Valley Delivery (120035)
Fruit's of a Vintner's Whinings (120043)
Premiums Paid (120051)
Training and Trading (120059)
Waiting on Weapons (120067)
ARM: Baderon's New Barbuts (120009)
Seeing Sallets to the See (120019)
A Step Ahead (120020)
Mailed Sailors (120021)
Running Rings (120036)
Watching the Shore (120044)
Watching the Knoll (120052)
Rings Around the Rock (120063)
Dead Ringers (120068)
GSM: Baderon's New Bands (120010)
2 x 2 Eyes (120022)
Going Brandanas (120041)
Brand New Brands (120049)
Staves to Fashion (120064)
LTW: Baderon's New Shoes (120008)
The Mad Tanner (120018)
Under Foot (120040)
Shoeing the Shore (120048)
Training and Tanning (120062)
WVR: Baderon's New Clothes (120006)
The Mad Hatter (120016)
Wear and Tear (120038)
Outfitting the Shore (120046)
Training and Tailoring (120060)
ALC: Baderon's New Soles (120011)
A Sticky Situation (120023)
Feeding Trainees (120042)
Suffering Soldiers (120050)
Training and Eating (120065)
CUL: Baderon's New Breakfast (120012)
Tall, Cool One (120024)
The Captain's Cravings (120025)
A Feast Fit for an Admiral (120026)
Supper at the Skull (120037)
The Last Supper (120045)
A Meal to Remember (120053)
Just Desserts (120066)
A Job Well Done (120069)
~~Gridania~~
CRP: A Mother's Carpentry (120203)
Shields for the Masses (120211)
Canes for the Citizens (120212)
High Tension (120213)
Bowing to Pressure (120223)
Pole Positioning (120229)
Driving up the Wall (120237)
Restocking the Stockade (120245)
Plinks Aplenty (120247)
BSM: A Mother's Metallurgy (120201)
It's All in the File (120209)
Training in Bentbranch (120221)
Re-crating the Scene (120231)
Training in Emerald Moss (120239)
ARM: A Mother's Foundry (120205)
Tending to Tendons (120217)
A Little Rusty (120225)
Springripple Rising (120233)
In Sod We Rust (120241)
GSM: A Mother's Jewelry (120206)
The Band's Bands (120218)
Dusting the Knuckles (120226)
In Arm's Reach (120234)
Knuckling Down (120242)
LTW: A Mother's Booties (120204)
Strapped for Straps (120214)
Fire and Hide (120215)
Choke Hold (120216)
Work of Friction (120224)
Hungry Like the Wolves (120230)
Back in the Harness (120238)
Morbol Measures (120246)
Harnessing Help (120248)
WVR: A Mother's Frippery (120202)
Quelling Bloody Rumors (120210)
Clearing Bentbranch (120222)
Clearing Nine Ivies (120232)
Clearing Emerald Moss (120240)
ALC: A Mother's Delicacies (120207)
Mixing It Up (120219)
Keeping It Green (120227)
Arboreal Alchemy (120235)
Growing Strains (120243)
CUL: A Mother's Muselix (120208)
Better Baker's Bounty (120220)
On a Full Belly (120228)
A Well-Deserved Dinner (120236)
Seafood Smorgasbord (120244)
~~Uldah~~
CRP: Momodi's Sturdy Supports (120403)
The Walk of Death (120413)
Pointed Ambitions (120425)
Off With Their Heads (120435)
Act of Pure Weevil (120443)
BSM: Momodi's Dancing Daggers (120401)
Pointy Props (120409)
Hammering the Point (120423)
Molten Metal (120434)
Looking to Horizon (120442)
ARM: Momodi's Sturdy Suits (120405)
Battered and Bent (120415)
Arming the Unarmed (120427)
Provisioning Drybone (120437)
Buckling Under (120445)
GSM: Momodi's Radiant Rings (120406)
A Scarcity of Scepters (120416)
Pleasure and Pain (120417)
In the Sultana's Wake (120418)
A Shining Example (120428)
A Drybone Induction (120432)
A Horizon Promotion (120440)
A Bluefog Induction (120448)
A Broken Water Promotion (120451)
LTW: Momodi's Sashed Shoes (120404)
Showing Some Leg (120414)
World-weary Souls (120426)
Camp Drybone Cares (120436)
I Would Walk 500 Malms (120444)
WVR: Momodi's Budget Breeches (120402)
Just for Kecks (120410)
Pants Make the Man (120411)
Holes in Their Defense (120412)
Hanging by a Thread (120424)
Exposed to the Elements (120433)
Busier Than the Blades (120441)
A Spot in the Shade (120449)
Fire on the Water (120452)
ALC: Momodi's Condiment Conundrum (120407)
Exports of Import (120419)
Fertile Lies (120420)
A Blind Fool (120421)
Saint Allene's Fire (120429)
Treating Steel (120431)
Blue in the Eye (120439)
Preserving the Region (120447)
Provisioning Broken Water (120450)
CUL: Momodi's Breakfast Bread (120408)
Finger Food (120422)
Irrational Behavior (120430)
Tender Victuals (120438)
Some Like It Wet (120446)
--]]
require ("global")
local limsaLocalLeves = {
{120007, 120017, 120039, 120047, 120061}, --CRP
{120005, 120013, 120014, 120015, 120035, 120043, 120051, 120059, 120067}, --BSM
{120009, 120019, 120020, 120021, 120036, 120044, 120052, 120063, 120068}, --ARM
{120010, 120022, 120041, 120049, 120064}, --GSM
{120008, 120018, 120040, 120048, 120062}, --LTW
{120006, 120016, 120038, 120046, 120060}, --WVR
{120011, 120023, 120042, 120050, 120065}, --ALC
{120012, 120024, 120025, 120026, 120037, 120045, 120053, 120066, 120069} --CUL
};
local gridaniaLocalLeves = {
{120203, 120211, 120212, 120213, 120223, 120229, 120237, 120245, 120247}, --CRP
{120201, 120209, 120221, 120231, 120239}, --BSM
{120205, 120217, 120225, 120233, 120241}, --ARM
{120206, 120218, 120226, 120234, 120242}, --GSM
{120204, 120214, 120215, 120216, 120224, 120230, 120238, 120246, 120248}, --LTW
{120202, 120210, 120222, 120232, 120240}, --WVR
{120207, 120219, 120227, 120235, 120243}, --ALC
{120208, 120220, 120228, 120236, 120244} --CUL
};
local uldahLocalLeves = {
{120403, 120413, 120425, 120435, 120443}, --CRP
{120401, 120409, 120423, 120434, 120442}, --BSM
{120405, 120415, 120427, 120437, 120445}, --ARM
{120406, 120416, 120417, 120418, 120428, 120432, 120440, 120448, 120451}, --GSM
{120404, 120414, 120426, 120436, 120444}, --LTW
{120402, 120410, 120411, 120412, 120424, 120433, 120441, 120449, 120452}, --WVR
{120407, 120419, 120420, 120421, 120429, 120431, 120439, 120447, 120450}, --ALC
{120408, 120422, 120430, 120438, 120446} --CUL
};
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local leveAllowances = 16;
local quest = 120438;
callClientFunction(player, "confirmJournal", quest, 1);
callClientFunction(player, "confirmJournal", quest, 2);
callClientFunction(player, "confirmJournal", quest, 3);
callClientFunction(player, "confirmJournal", quest, 4);
--[[callClientFunction(player, "talkOfferWelcome", player, leveAllowances);
while (true) do
-- Class Menu
local classChoice = callClientFunction(player, "askOfferPack");
if (classChoice != nil) then
while (true) do
-- Level Difficulty Menu
local levelChoice = callClientFunction(player, "askOfferRank");
if levelChoice != nil then
if levelChoice == 1 then
local levequest = callClientFunction(player, "askOfferQuest", player, 1, 120438, 120025);
if (levequest != nil and levequest > 0) then
player:SendMessage(0x20, "", "[DEBUG] Leve : " .. tostring(pickedLeve));
player:SendGameMessage(GetWorldMaster(), 50141, 0x20, leveAllowances);
end
elseif levelChoice == 2 then
pickedLeve = callClientFunction(player, "askOfferQuest", player, 1, 120026, 120027);
if (pickedLeve != nil) or (pickedLeve != -1) then
player:SendMessage(0x20, "", "[DEBUG] Leve : " .. tostring(pickedLeve));
player:SendGameMessage(GetWorldMaster(), 50141, 0x20, leveAllowances);
end
elseif levelChoice == 3 then
pickedLeve = callClientFunction(player, "askOfferQuest", player, 1, 120028, 120029);
if (pickedLeve != nil) or (pickedLeve != -1) then
player:SendMessage(0x20, "", "[DEBUG] Leve : " .. tostring(pickedLeve));
player:SendGameMessage(GetWorldMaster(), 50141, 0x20, leveAllowances)
end
end
else
break
end
end
else
break;
end
end]]--
callClientFunction(player, "finishTalkTurn");
player:EndEvent();
end
function getAvailableLeves(class, rank)
end

View File

@@ -0,0 +1,28 @@
--[[
PopulaceItemRepairer Script
Functions:
INIT: speechType, townType
talkWelcome(player, bool, number, bool) - Opens the main menu
selectItem(nil, pageNumber, ?, condition1, condition2, condition3, condition4, condition5) - "Ain't running a charity here", message said when you have insufficent funds
confirmRepairItem(player, price, itemId, hq grade) - Shows the confirm box for item repair.
confirmUseFacility(player, price) - Shows confirm box for using facility. Default price is 11k?
finishTalkTurn() - Call at end to stop npc from staring at the player (eeeek)
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
result = callClientFunction(player, "eventTalkStep14");
player:EndEvent();
end

View File

@@ -0,0 +1,145 @@
--[[
PopulaceRetainerManager Script
Functions:
eventTalkStep1(true) - Intro tutorial if no retainer
newEventTalkStep1(sayIntro) - Seems to be a post-Tanaka version of the intro????
eventTalkStep2() - Choose retainer yourself (go to race select) or let npc do it
eventTaklSelectCutSeane(cutsceneName, actorClassId1, actorClassId2, actorClassId3, actorClassId4, actorClassId5) - Starts the advance cutscene to choose a retainer. 5 retainer actorClassId's are given.
eventTalkStep4(actorClassId) - Opens up the retainer naming dialog
eventTalkStepFinalAnswer(actorClassId) - Confirm Dialog
eventTalkStepError(errorCode) - Error dialog, 1: No Extra Retainers, 2: Server Busy.
eventTalkStepFinish()
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local npcActorClass = npc:GetActorClassId()
local retainerIndex = 3001100;
local cutscene = "rtn0l010" -- Defaulting to Limsa for now for testing
if npcActorClass == 1000166 then
cutscene = "rtn0l010";
retainerIndex = 3001101;
elseif npcActorClass == 1000865 then
cutscene = "rtn0u010";
retainerIndex = 3002101;
elseif npcActorClass == 1001184 then
cutscene = "rtn0g010";
retainerIndex = 3003101;
else
return;
end
introChoice = callClientFunction(player, "newEventTalkStep1", false);
if (introChoice == 1) then
-- Choose Retainer or Random
raceChoice = callClientFunction(player, "eventTalkStep2");
while (true) do
if (retainerChoice == 0) then
raceChoice = callClientFunction(player, "eventTalkStep22");
end
if (raceChoice == 0) then
--Choose random actorId from a valid set for the city
math.randomseed(os.time());
local randomRetainer = math.random(retainerIndex, (retainerIndex+74));
retainerName = callClientFunction(player, "eventTalkStep4", randomRetainer);
if (retainerName ~= "") then
confirmChoice = callClientFunction(player, "eventTalkStepFinalAnswer", randomRetainer);
if (confirmChoice == 1) then
callClientFunction(player, "eventTalkStepFinish");
player:EndEvent();
return;
elseif (confirmChoice == 3) then
raceChoice = 0;
else
player:EndEvent();
return;
end
else
callClientFunction(player, "eventTalkStepBreak");
raceChoice = -1;
end
elseif (raceChoice > 0) and (raceChoice < 16) then
--Choose 5 random but correct actor ids for the city and race/tribe
local retainerRace = ((retainerIndex) + (5*(raceChoice-1)));
local retainerRaceChoices = {retainerRace, retainerRace+1, retainerRace+2, retainerRace+3, retainerRace+4};
-- Randomize the appearance order of the available five
shuffle(retainerRaceChoices);
retainerChoice = callClientFunction(player, "eventTaklSelectCutSeane", cutscene, retainerRaceChoices[1], retainerRaceChoices[2], retainerRaceChoices[3], retainerRaceChoices[4], retainerRaceChoices[5]);
if (retainerChoice == -1) then
player:EndEvent();
return;
elseif (retainerChoice > 0) then
--Retainer chosen, choose name
retainerName = callClientFunction(player, "eventTalkStep4", retainerRaceChoices[retainerChoice]);
if (retainerName ~= "") then
confirmChoice = callClientFunction(player, "eventTalkStepFinalAnswer", retainerRaceChoices[retainerChoice]);
if (confirmChoice == 1) then
callClientFunction(player, "eventTalkStepFinish");
player:EndEvent();
return;
elseif (confirmChoice == 3) then
retainerChoice = 0;
else
player:EndEvent();
return;
end
else
callClientFunction(player, "eventTalkStepBreak");
raceChoice = -1;
end
end
else
break;
end
end
end
player:EndEvent();
end
function shuffle(tbl)
for i = #tbl, 2, -1 do
local j = math.random(i)
tbl[i], tbl[j] = tbl[j], tbl[i]
end
return tbl
end

View File

@@ -0,0 +1,83 @@
--[[
PopulaceSpecialEventCryer Script
Actor Class script to handle the 6 NPCs (technically 3, the actors were duped) involved in the Foundation Day 2011 & 2012 events.
In 2011 they appear to be used for recruitment information for their respective Grand Company.
In 2012, they were used for exchanging Over-aspected Crystals/Clusters for GC seals as part of the ongoing Atomos event.
Functions:
For 2011.
eventTalkStep0(joined) - NPC dialog about joining their cause to fight back Imperials. joined = 0 or 1. Function has hardcoded actor IDs, won't work with 2012 versions
eventTalkNotGCmenber(npcGC) - NPC dialog when you're not part of their grand company.
For 2012.
eventTalkCrystalExchange(player, npcGC, hasCrystal) - NPC dialog explaining they want over-aspected crystals. Brings up crystal exchange prompt if hasCrystal = 1.
eventTalkCsOverflow(player, npcGC) - Error message that you can't hold the seals being offered.
eventTalkCrystalExchange2(player, npcGC) - NPC dialog for accepting exchange of crystals for seals
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
local gcRep = {
[1001619] = 1, -- Maelstrom Representative 2011
[1002105] = 1, -- Maelstrom Representative 2012
[1001623] = 2, -- Adder Representative 2011
[1002109] = 2, -- Adder Representative 2012
[1001627] = 3, -- Flame Representative 2011
[1002113] = 3, -- Flame Representative 2012
}
function onEventStarted(player, npc, triggerName)
local playerGC = player.gcCurrent;
local npcId = npc:GetActorClassId();
local npcGC = gcRep[npcId];
local npcGCSeal = 1000200 + npcGC;
local hasCrystal = 1;
local crystal = 3020537;
local cluster = 3020413;
local eventMode = 2012;
if eventMode == 2011 then
if playerGC == 0 then
callClientFunction(player, "eventTalkStep0", 0);
elseif playerGC == npcGC then
callClientFunction(player, "eventTalkStep0", 1);
else
callClientFunction(player, "eventTalkNotGCmenber", npcGC);
end
elseif eventMode == 2012 then
choice = callClientFunction(player, "eventTalkCrystalExchange", player, npcGC, hasCrystal);
if choice == 1 then
--callClientFunction(player, "eventTalkCsOverflow", player, npcGC);
player:SendMessage(0x20, "", "You pretend to hand over four over-aspected crystals.");
callClientFunction(player, "eventTalkCrystalExchange2", player, npcGC);
local invCheck = player:GetItemPackage(INVENTORY_CURRENCY):AddItem(npcGCSeal, 1000, 1);
if invCheck == INV_ERROR_SUCCESS then
player:SendGameMessage(player, GetWorldMaster(), 25071, MESSAGE_TYPE_SYSTEM, crystal, 1, npcGCSeal, 1, 4, 1000);
end
elseif choice == 2 then
player:SendMessage(0x20, "", "You pretend to hand over an over-aspected cluster.");
--callClientFunction(player, "eventTalkCsOverflow", player, npcGC);
callClientFunction(player, "eventTalkCrystalExchange2", player, npcGC);
local invCheck = player:GetItemPackage(INVENTORY_CURRENCY):AddItem(npcGCSeal, 3000, 1);
if invCheck == INV_ERROR_SUCCESS then
player:SendGameMessage(player, GetWorldMaster(), 25071, MESSAGE_TYPE_SYSTEM, cluster, 1, npcGCSeal, 1, 1, 3000);
end
end
end
player:EndEvent();
end

View File

@@ -0,0 +1,97 @@
require("global");
--[[
Populace Standard Script
Functions:
eventSwitch(questId1, questId2, questId3, questId4, currentPage, maxPages, titleId) - Shows a dialog box with which quest to trigger
when more than one quest is active for this npc.
Notes:
This scripts fires for all normal standard ENpcs in the world. Because of how the FFXIV dialog system works, everything is technically
a quest; including the DefaultTalk responses. This script checks both static default quests and any relevant ones for that actor class
id. If only one exists; it is automatically triggered otherwise a dialog box will appear for the player to choose what quest to do.
--]]
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, eventType, eventName)
local chosenQuest = nil;
if (eventType == 1) then
local defaultTalk = player:GetDefaultTalkQuest(npc);
local tutorialTalk = player:GetTutorialQuest(npc);
local activeQuests = player:GetQuestsForNpc(npc);
local possibleQuests = {};
-- Create the switch table for this npc
if (defaultTalk ~= nil and eventType == ETYPE_TALK) then
table.insert(possibleQuests, defaultTalk);
end
if (tutorialTalk ~= nil and eventType == ETYPE_TALK) then
table.insert(possibleQuests, tutorialTalk);
end
if (activeQuests ~= nil) then
for i=1,#activeQuests do
table.insert(possibleQuests, activeQuests[i]);
end
end
-- Either let the player choose the quest or start it if it's the only one.
if (#possibleQuests > 1) then
local currentPage = 0;
local numPages = math.floor((#possibleQuests-1)/4) + 1;
while (true) do
local page, index = callClientFunction(player, "switchEvent", possibleQuests[currentPage * 4 + 1], possibleQuests[currentPage * 4 + 2], possibleQuests[currentPage * 4 + 3], possibleQuests[currentPage * 4 + 4], currentPage + 1, numPages, 0x3F1);
if (page == 0) then
chosenQuest = possibleQuests[(currentPage * 4) + index];
break;
elseif (page > 0) then
currentPage = page - 1;
else
player:EndEvent();
return;
end
end
elseif (#possibleQuests == 1) then
chosenQuest = possibleQuests[1];
end
else
local activeQuests = player:GetQuestsForNpc(npc);
if (#activeQuests != 0) then
chosenQuest = activeQuests[1];
end
end
-- Run the quest event or tell the devs it's missing.
if (chosenQuest ~= nil) then
doQuestEvent(player, npc, chosenQuest, eventType, eventName);
else
local msg = string.format("ERROR: This PopulaceStandard actor has no defaultTalk or quest set. \nActor Class Id: %s\nEvent Name: %s", tostring(npc:GetActorClassId()), eventName);
printf(msg);
player:SendMessage(0x20, "", msg);
player:EndEvent();
end
end
function doQuestEvent(player, npc, quest, eventType, eventName)
if (eventType == 0) then
quest:OnCommand(player, npc, eventName);
elseif (eventType == 1) then
quest:OnTalk(player, npc);
elseif (eventType == 2) then
quest:OnPush(player, npc, eventName);
elseif (eventType == 3) then
quest:OnEmote(player, npc, eventName);
elseif (eventType == 5) then
quest:OnNotice(player, npc, eventName);
end
end

View File

@@ -0,0 +1,56 @@
--[[
InstanceRaidGuide Script
Functions;
askEnterInstanceRaid(arg1) -- Opens a widget asking to enter the given Raid id.
--]]
require ("global")
function init(npc)
if ((npc == 1002090) or (npc == 1002091)) then
-- This won't work due to how init() works, but old scripts had it, keeping it here for now
return false, false, 0, 0, 491, 2;
else
return false, false, 0, 0;
end
end
function onEventStarted(player, npc, eventType, eventName)
npcId = npc:GetActorClassId()
if (npcId == 1002090) then -- Serpent Private Hodder (Stewart) : Gcl107
callClientFunction(player, "delegateEvent", player, GetStaticActor("DftFst"), "defaultTalkWithStewart_001"); -- "defaultTalkWithStewart_002" -- Post-Raid dialog?
--[[
choice = callClientFunction(player, "delegateEvent", player, GetStaticActor("Gcl107"), "processEventStewart", 15);
if (choice == 1) then
callClientFunction(player, "askEnterInstanceRaid", 15); -- Rivenroad
end
--]]
elseif (npcId == 1002091) then -- Serpent Private Dauremant (Trisselle) : Sum6w0
callClientFunction(player, "delegateEvent", player, GetStaticActor("DftFst"), "defaultTalkWithTrisselle_001"); -- "defaultTalkWithTrisselle_002" -- No idea for context.
--[[
choice = callClientFunction(player, "delegateEvent", player, GetStaticActor("Sum6w0"), "processEventTrisselle", 16)
if (choice == 1) then
callClientFunction(player, "askEnterInstanceRaid", 16); -- Rivenroad (Hard)
end
--]]
elseif (npcId == 1060022) then -- Louisoix
callClientFunction(player, "delegateEvent", player, GetStaticActor("DftFst"), "defaultTalkLouisoix_001");
end
player:EndEvent();
end

View File

@@ -0,0 +1,107 @@
--[[
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 ("shop")
function init(npc)
return false, false, 0, 0;
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)
local npcId = npc:GetActorClassId();
local saySheetId = guildShopInfo[npcId][1];
local shopCurrency = guildShopInfo[npcId][2];
local gilCurrency = 1000001;
local keepersHymn = 3020410;
local shopPack = 0;
callClientFunction(player, "welcomeTalk", nil, saySheetId, player);
while (true) do
local choice = callClientFunction(player, "selectMode", nil, npcId, true, shopCurrency, 100);
if (choice == 3) then -- Undo Point Allotment
-- TODO: Add point reset handling
elseif (choice == 4) then -- Leave menu selected
player:EndEvent();
break;
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:GetItemPackage(INVENTORY_CURRENCY):GetItemQuantity(shopCurrency);
purchaseItem(player, INVENTORY_CURRENCY, gilCurrency, markAmount*4, 1, markAmount, shopCurrency);
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

View File

@@ -0,0 +1,655 @@
--[[
PopulaceShopSalesman Script
Functions:
welcomeTalk(sheetId, player) - Start Message
selectMode(askMode) - Shows buy/sell modes. If askmode > 0 show guild tutorial. If askmode == -7/-8/-9 show nothing. Else show affinity/condition tutorials.
selectModeOfClassVendor() - Opens categories for class weapons and gear
selectModeOfMultiWeaponVendor(consumptionmenuId) - Opens categories for weapons/tools (war/magic/land/hand). Arg consumptionmenuId appends location of item repair person. -1: Ul'dah, -2: Gridania, -3: Limsa
selectModeOfMultiArmorVendor(consumptionmenuId) - Opens categories for armor in different slots. Arg consumptionmenuId appends location of item repair person. -1: Ul'dah, -2: Gridania, -3: Limsa
openShopBuy(player, shopPack, CurrencyItemId) - ShopPack: Items to appear in window. CurrencyItemId: What is being used to buy these items.
selectShopBuy(player) - Call after openShopBuy() to open widget
closeShopBuy(player) - Closes the buy window
openShopSell(player) - Call this to open sell window
selectShopSell(player) - Call after openShopSell()
closeShopSell(player) - Closes the sell window
confirmSellingItem(itemId, quality, quantity, gil) - Simple Sell confirmation window
selectFacility(?, sheetId, 3) - Opens the facility chooser.
confirmUseFacility(player, cost) - Facility cost confirm
informSellPrice(1, chosenItem, price) - Shows sell confirm window. ChosenItem must be correct.
startTutorial(nil, menuId) - Opens up a tutorial menu for each guild type based on menuId
finishTalkTurn() - Done at the end.
--]]
require ("global")
require ("shop")
shopInfo = {
--[[
[actorclass id] =
{
welcomeText - Dialog for the NPC to speak when interacting
menuId, - Displays certain menu/dialog. 29-36 = DoH Facilities menus. -1 Ul'dah, -2 Gridania, -3 Limsa. -7/-8/-9/nil show nothing
shopMode, - Type of shop. 0 = Single shop pack, 1 = Class vendor, 2 = Weapon vendor, 3 = Armor vendor, 4 = Hamlet vendor
shopPack{s}, - The item table index to send the client containing the list of items to display, shopmode 2/3 have a static list
}
--]]
[1000159] = {34, 36, 0, 1016},
[1000163] = {49, 31, 0, 1017},
[1000165] = {74, -8, 0, 1019},
[1001458] = {44, 30, 0, 1018},
[1500142] = {266, -1, 0, 5001},
[1500143] = {267, -1, 0, 5002},
[1500144] = {268, -1, 0, 5003},
[1500145] = {269, -1, 0, 5004},
[1500146] = {269, -1, 0, 5005},
[1500147] = {270, -1, 0, 5006},
[1500150] = {266, -8, 0, 5001},
[1500151] = {267, -8, 0, 5002},
[1500152] = {268, -8, 0, 5003},
[1500153] = {269, -8, 0, 5004},
[1500154] = {269, -8, 0, 5005},
[1500155] = {270, -8, 0, 5006},
[1500158] = {266, -8, 0, 5001},
[1500159] = {267, -8, 0, 5002},
[1500160] = {268, -8, 0, 5003},
[1500161] = {269, -8, 0, 5004},
[1500162] = {269, -8, 0, 5005},
[1500163] = {270, -8, 0, 5006},
[1500401] = {317, -8, 0, 1013},
[1500405] = {320, -8, 0, 1013},
[1500407] = {321, -8, 0, 1012},
[1500411] = {322, -8, 0, 2017},
[1500414] = {324, -8, 0, 1012},
[1500419] = {327, -8, 0, 1012},
[1500422] = {332, -8, 0, 1013},
[1500423] = {331, -8, 0, 2017},
[1500429] = {328, -8, 0, 2017},
[1500430] = {281, -8, 4, 5122},
[1500431] = {281, -8, 4, 5118},
[1500432] = {281, -8, 4, 5120},
[1600001] = {6, -8, 0, 1006},
[1600002] = {7, -8, 0, 1007},
[1600003] = {8, -8, 0, 1008},
[1600004] = {9, -8, 0, 1009},
[1600005] = {10, -8, 0, 1010},
[1600006] = {11, -8, 0, 1011},
[1600007] = {12, -8, 0, 1012},
[1600008] = {13, -8, 0, 1013},
[1600009] = {14, -8, 0, 1014},
[1600010] = {15, -8, 0, 1015},
[1600011] = {1, -8, 0, 1001},
[1600012] = {2, -8, 0, 1002},
[1600013] = {3, -8, 0, 1003},
[1600014] = {4, -8, 0, 1004},
[1600016] = {5, -8, 0, 1005},
[1600017] = {39, 29, 0, 2020},
[1600018] = {59, 33, 0, 2021},
[1600019] = {75, -8, 0, 2022},
[1600020] = {77, -8, 0, 2010},
[1600021] = {78, -8, 0, 2011},
[1600022] = {79, -8, 0, 2012},
[1600023] = {80, -8, 0, 2013},
[1600024] = {81, -8, 0, 2014},
[1600025] = {82, -8, 0, 2015},
[1600026] = {83, -8, 0, 2016},
[1600027] = {84, -8, 0, 2017},
[1600028] = {85, -8, 0, 2018},
[1600029] = {86, -8, 0, 2019},
[1600030] = {87, -8, 0, 2001},
[1600031] = {88, -8, 0, 2003},
[1600032] = {89, -8, 0, 2002},
[1600033] = {90, -8, 0, 2004},
[1600034] = {91, -8, 0, 2005},
[1600035] = {92, -8, 0, 2006},
[1600036] = {93, -8, 0, 2007},
[1600037] = {94, -8, 0, 2008},
[1600039] = {69, 35, 0, 3020},
[1600040] = {54, 32, 0, 3019},
[1600041] = {64, 34, 0, 3021},
[1600042] = {76, -8, 0, 3022},
[1600043] = {96, -8, 0, 3009},
[1600044] = {97, -8, 0, 3010},
[1600045] = {98, -8, 0, 3011},
[1600046] = {99, -8, 0, 3012},
[1600047] = {100, -8, 0, 3013},
[1600048] = {101, -8, 0, 3014},
[1600049] = {102, -8, 0, 3016},
[1600050] = {103, -8, 0, 3015},
[1600051] = {104, -8, 0, 3017},
[1600052] = {105, -8, 0, 3004},
[1600053] = {106, -8, 0, 3007},
[1600054] = {107, -8, 0, 3018},
[1600055] = {108, -8, 0, 3006},
[1600056] = {109, -8, 0, 3005},
[1600057] = {110, -8, 0, 3002},
[1600058] = {111, -8, 0, 3003},
[1600059] = {112, -8, 0, 3001},
[1600061] = {95, -8, 0, 2009},
[1600062] = {113, -8, 0, 3008},
[1600063] = {114, -8, 0, 4001},
[1600064] = {235, -8, 0, 2023},
[1600065] = {236, -8, 0, 1020},
[1600066] = {237, -8, 0, 3023},
[1600067] = {238, -8, 0, 5007},
[1600068] = {239, -8, 0, 5007},
[1600069] = {240, -1, 0, 5007},
[1600070] = {241, -8, 0, 5008},
[1600071] = {242, -8, 0, 5008},
[1600072] = {243, -8, 0, 5008},
[1600073] = {244, -8, 1, 5009},
[1600074] = {245, -8, 1, 5015},
[1600075] = {246, -8, 1, 5021},
[1600076] = {247, -8, 1, 5027},
[1600077] = {248, -8, 1, 5033},
[1600078] = {249, -8, 1, 5039},
[1600079] = {250, -8, 1, 5045},
[1600080] = {251, -8, 1, 5051},
[1600081] = {252, -8, 1, 5057},
[1600082] = {253, -8, 1, 5063},
[1600083] = {254, -8, 1, 5069},
[1600084] = {255, -8, 1, 5075},
[1600085] = {256, -8, 1, 5081},
[1600086] = {257, -8, 1, 5087},
[1600087] = {258, -8, 1, 5093},
[1600088] = {259, -8, 1, 5099},
[1600089] = {260, -8, 1, 5105},
[1600090] = {261, -8, 1, 5111},
[1600092] = {263, -8, 0, 2024},
[1600093] = {264, -8, 0, 1021},
[1600094] = {265, -8, 0, 3024},
[1600095] = {281, -8, 0, 1005},
[1600096] = {281, -8, 0, 2009},
[1600097] = {281, -8, 0, 4001},
[1600098] = {281, -8, 0, 4002},
[1600099] = {281, -8, 0, 2009},
[1600100] = {281, -2, 2, 0},
[1600101] = {281, -8, 0, 2009},
[1600103] = {281, -8, 0, 3008},
[1600104] = {281, -8, 0, 3008},
[1600107] = {281, -8, 3, 0},
[1600108] = {281, -8, 0, 3008},
[1600109] = {281, -3, 2, 0},
[1600110] = {281, -8, 0, 4001},
[1600111] = {281, -8, 0, 2009},
[1600112] = {281, -8, 0, 4002},
[1600113] = {281, -8, 0, 4001},
[1600117] = {281, -8, 0, 2009},
[1600119] = {281, -2, 3, 0},
[1600120] = {281, -8, 0, 3008},
[1600121] = {281, -8, 0, 2009},
[1600122] = {281, -8, 0, 3008},
[1600125] = {281, -8, 0, 1005},
[1600126] = {281, -8, 0, 3008},
[1600129] = {281, -1, 3, 0},
[1600130] = {281, -8, 0, 4001},
[1600133] = {281, -1, 2, 0},
[1600137] = {281, -8, 0, 1005},
[1600142] = {281, -8, 0, 1005},
}
shopRange = { --shopRangeStart, shopRangeEnd
[101] = {101001, 101010};
[102] = {102001, 102010};
[103] = {103001, 103010};
[104] = {104001, 104010};
[105] = {105001, 105010};
[106] = {106001, 106010};
[107] = {107001, 107010};
[108] = {108001, 108017};
[109] = {109001, 109015};
[110] = {110001, 110018};
[111] = {111001, 111018};
[112] = {112001, 112018};
[113] = {113001, 113019};
[114] = {114001, 114015};
[115] = {115001, 115015};
[116] = {116001, 116010};
[117] = {117001, 117010};
[118] = {118001, 118010};
[120] = {120001, 120012};
[121] = {121001, 121012};
[122] = {122001, 122012};
[123] = {123001, 123012};
[124] = {124001, 124012};
[125] = {125001, 125012};
[126] = {126001, 126012};
[127] = {127001, 127012};
[128] = {128001, 128012};
[129] = {129001, 129016};
[130] = {130001, 130012};
[131] = {131001, 131012};
[132] = {132001, 132012};
[133] = {133001, 133012};
[134] = {134001, 134016};
[135] = {135001, 135012};
[136] = {136001, 136012};
[137] = {137001, 137012};
[138] = {138001, 138012};
[139] = {139001, 139012};
[140] = {140001, 140012};
[141] = {141001, 141012};
[142] = {142001, 142012};
[143] = {143001, 143016};
[144] = {144001, 144018};
[145] = {1071001, 1071002};
[146] = {1072001, 1072006};
[1001] = {1001001, 1001008};
[1002] = {1002001, 1002008};
[1003] = {1003001, 1003007};
[1004] = {1004001, 1004002};
[1005] = {1005001, 1005017};
[1006] = {1006001, 1006006};
[1007] = {1007001, 1007010};
[1008] = {1008001, 1008009};
[1009] = {1009001, 1009012};
[1010] = {1010001, 1010014};
[1011] = {1011001, 1011010};
[1012] = {1012001, 1012007};
[1013] = {1013001, 1013011};
[1014] = {1014001, 1014006};
[1015] = {1015001, 1015007};
[1016] = {1016001, 1016016};
[1017] = {1018001, 1018010};
[1018] = {1017001, 1017013};
[1019] = {1019001, 1019005};
[1020] = {1066001, 1066004};
[1021] = {1069001, 1069005};
[2001] = {1020001, 1020008};
[2002] = {1021001, 1021006};
[2003] = {1022001, 1022007};
[2004] = {1023001, 1023008};
[2005] = {1024001, 1024003};
[2006] = {1025001, 1025008};
[2007] = {1026001, 1026006};
[2008] = {1027001, 1027004};
[2009] = {1028001, 1028016};
[2010] = {1029001, 1029009};
[2011] = {1030001, 1030008};
[2012] = {1031001, 1031010};
[2013] = {1032001, 1032010};
[2014] = {1033001, 1033012};
[2015] = {1034001, 1034015};
[2016] = {1035001, 1035013};
[2017] = {1036001, 1036006};
[2018] = {1037001, 1037006};
[2019] = {1038001, 1038008};
[2020] = {1039001, 1039009};
[2021] = {1040001, 1040010};
[2022] = {1041001, 1041005};
[2023] = {1065001, 1065006};
[2024] = {1068001, 1068006};
[3001] = {1042001, 1042008};
[3002] = {1043001, 1043008};
[3003] = {1044001, 1044008};
[3004] = {1045001, 1045008};
[3005] = {1046001, 1046010};
[3006] = {1047001, 1047008};
[3007] = {1048001, 1048006};
[3008] = {1049001, 1049016};
[3009] = {1050001, 1050013};
[3010] = {1051001, 1051008};
[3011] = {1052001, 1052009};
[3012] = {1053001, 1053010};
[3013] = {1054001, 1054006};
[3014] = {1055001, 1055013};
[3015] = {1056001, 1056005};
[3016] = {1057001, 1057008};
[3017] = {1058001, 1058011};
[3018] = {1059001, 1059007};
[3019] = {1060001, 1060011};
[3020] = {1061001, 1061014};
[3021] = {1062001, 1062016};
[3022] = {1063001, 1063004};
[3023] = {1067001, 1067008};
[3024] = {1070001, 1070004};
[4001] = {1064001, 1064011};
[4002] = {1064001, 1064011};
[5001] = {2001001, 2001018};
[5002] = {2002001, 2002006};
[5003] = {2003001, 2003010};
[5004] = {2004001, 2004009};
[5005] = {2005001, 2005010};
[5006] = {2006001, 2006012};
[5007] = {2007001, 2007010};
[5008] = {2008001, 2008016};
[5009] = {2009001, 2009007};
[5010] = {2009101, 2009104};
[5011] = {2009201, 2009204};
[5012] = {2009301, 2009304};
[5013] = {2009401, 2009404};
[5014] = {2009501, 2009504};
[5015] = {2010001, 2010004};
[5016] = {2010101, 2010104};
[5017] = {2010201, 2010204};
[5018] = {2010301, 2010304};
[5019] = {2010401, 2010404};
[5020] = {2010501, 2010504};
[5021] = {2011001, 2011004};
[5022] = {2011101, 2011104};
[5023] = {2011201, 2011204};
[5024] = {2011301, 2011304};
[5025] = {2011401, 2011404};
[5026] = {2011501, 2011504};
[5027] = {2012001, 2012007};
[5028] = {2012101, 2012104};
[5029] = {2012201, 2012204};
[5030] = {2012301, 2012304};
[5031] = {2012401, 2012404};
[5032] = {2012501, 2012504};
[5033] = {2013001, 2013004};
[5034] = {2013101, 2013104};
[5035] = {2013201, 2013204};
[5036] = {2013301, 2013304};
[5037] = {2013401, 2013404};
[5038] = {2013501, 2013504};
[5039] = {2014001, 2014007};
[5040] = {2014101, 2014104};
[5041] = {2014201, 2014204};
[5042] = {2014301, 2014304};
[5043] = {2014401, 2014404};
[5044] = {2014501, 2014504};
[5045] = {2015001, 2015007};
[5046] = {2015101, 2015104};
[5047] = {2015201, 2015204};
[5048] = {2015301, 2015304};
[5049] = {2015401, 2015404};
[5050] = {2015501, 2015504};
[5051] = {2016001, 2016006};
[5052] = {2016101, 2016104};
[5053] = {2016201, 2016204};
[5054] = {2016301, 2016304};
[5055] = {2016401, 2016404};
[5056] = {2016501, 2016504};
[5057] = {2017001, 2017006};
[5058] = {2017101, 2017104};
[5059] = {2017201, 2017204};
[5060] = {2017301, 2017304};
[5061] = {2017401, 2017404};
[5062] = {2017501, 2017504};
[5063] = {2018001, 2018006};
[5064] = {2018101, 2018104};
[5065] = {2018201, 2018204};
[5066] = {2018301, 2018304};
[5067] = {2018401, 2018404};
[5068] = {2018501, 2018504};
[5069] = {2019001, 2019006};
[5070] = {2019101, 2019104};
[5071] = {2019201, 2019204};
[5072] = {2019301, 2019304};
[5073] = {2019401, 2019404};
[5074] = {2019501, 2019504};
[5075] = {2020001, 2020006};
[5076] = {2020101, 2020104};
[5077] = {2020201, 2020204};
[5078] = {2020301, 2020304};
[5079] = {2020401, 2020404};
[5080] = {2020501, 2020504};
[5081] = {2021001, 2021006};
[5082] = {2021101, 2021104};
[5083] = {2021201, 2021204};
[5084] = {2021301, 2021304};
[5085] = {2021401, 2021404};
[5086] = {2021501, 2021504};
[5087] = {2022001, 2022006};
[5088] = {2022101, 2022104};
[5089] = {2022201, 2022204};
[5090] = {2022301, 2022304};
[5091] = {2022401, 2022404};
[5092] = {2022501, 2022504};
[5093] = {2023001, 2023006};
[5094] = {2023101, 2023104};
[5095] = {2023201, 2023204};
[5096] = {2023301, 2023304};
[5097] = {2023401, 2023404};
[5098] = {2023501, 2023504};
[5099] = {2024001, 2024006};
[5100] = {2024101, 2024104};
[5101] = {2024201, 2024204};
[5102] = {2024301, 2024304};
[5103] = {2024401, 2024404};
[5104] = {2024501, 2024504};
[5105] = {2025001, 2025006};
[5106] = {2025101, 2025104};
[5107] = {2025201, 2025204};
[5108] = {2025301, 2025304};
[5109] = {2025401, 2025404};
[5110] = {2025501, 2025504};
[5111] = {2026001, 2026006};
[5112] = {2026101, 2026104};
[5113] = {2026201, 2026204};
[5114] = {2026301, 2026304};
[5115] = {2026401, 2026404};
[5116] = {2026501, 2026504};
[5117] = {2026601, 2026606};
[5118] = {2026701, 2026708};
[5119] = {2026801, 2026808};
[5120] = {2026901, 2026908};
[5121] = {2027001, 2027008};
[5122] = {2027101, 2027110};
[5123] = {2027201, 2027211};
}
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
npcId = npc:GetActorClassId();
if shopInfo[npcId] == nil then
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;
local shopCurrency = 1000001;
local welcomeText = 1;
local menuId = shopInfo[npcId][2];
local shopCategory = shopInfo[npcId][3];
local itemShop = 0;
local classShop = 1;
local weaponShop = 2;
local armorShop = 3;
local hamletShop = 4;
local weaponShopPack = {5001,5002,5007,5008};
local armorShopPack = {5004,5005,5006,5003};
local menuBuy = 1;
local menuBuyCount = 1; -- For Shops with multiple buying categories
local menuSell = 2;
local menuFacility = 3;
local menuTutorial = 4;
local menuClose = -3;
local menuHasFacility = false;
local menuHasTutorial = false;
local shopPack = shopInfo[npcId][4]; -- Starting value for the shopPack of the current NPC Actor
local chosenShopPackage = 0; -- Var to send to openShopMenu() once desired shopPack is determined
local choice;
callClientFunction(player, "welcomeTalk", shopInfo[npcId][welcomeText], player);
while (true) do
if (shopCategory == itemShop) then
choice = callClientFunction(player, "selectMode", menuId);
menuHasFacility = true;
menuHasTutorial = true;
elseif (shopCategory == classShop) then
choice = callClientFunction(player, "selectModeOfClassVendor");
menuBuyCount = 6;
menuSell = 0;
elseif (shopCategory == weaponShop) then
choice = callClientFunction(player, "selectModeOfMultiWeaponVendor", menuId);
menuBuyCount = 4;
menuSell = 0;
elseif (shopCategory == armorShop) then
choice = callClientFunction(player, "selectModeOfMultiArmorVendor", menuId);
menuBuyCount = 4;
menuSell = 0;
elseif (shopCategory == hamletShop) then
choice = callClientFunction(player, "selectMode", menuId);
local hamletRegion = shopPack;
local hamletPackAleport = {5117, 5122, 5123};
local hamletPackHyrstmill = {5117, 5118, 5119};
local hamletPackGoldenBazaar = {5117, 5120, 5121};
local hamletLevel = 3; -- Defaulting to highest value for now
if hamletRegion == 5122 then -- Aleport
-- hamletLevel = GetHamletStatus(idAleport);
shopPack = hamletPackAleport[hamletLevel] or 5117;
elseif hamletRegion == 5118 then -- Hyrstmill
-- hamletLevel = GetHamletStatus(idHyrstmill);
shopPack = hamletPackHyrstmill[hamletLevel] or 5117;
elseif hamletRegion == 5120 then -- The Golden Bazaar
-- hamletLevel = GetHamletStatus(idGoldenBazaar);
shopPack = hamletPackGoldenBazaar[hamletLevel] or 5117;
end
end
if choice and (choice >= menuBuy and choice <= menuBuyCount) then
--player:SendMessage(0x20,"", "Menu option: "..choice);
if (shopCategory == weaponShop) then
chosenShopPackage = weaponShopPack[choice];
elseif (shopCategory == armorShop) then
chosenShopPackage = armorShopPack[choice];
else
chosenShopPackage = ((shopPack-1) + choice);
end
openShopMenu(
player,
menuId,
chosenShopPackage,
shopRange[chosenShopPackage][1],
shopRange[chosenShopPackage][2],
shopCurrency
);
elseif (choice == menuSell) then
openSellMenu(player);
elseif (choice == menuFacility) and (menuHasFacility == true) then
if menuId > 0 then
local classFacility = (shopInfo[npcId][1] + 1) or 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
end
elseif (choice == menuTutorial) and (menuHasTutorial == true) then
callClientFunction(player, "startTutorial", nil, menuId);
end
if (choice == menuClose or choice == nil) then
break;
end
end
callClientFunction(player, "finishTalkTurn", player);
player:EndEvent();
end
function openShopMenu(player, menuId, shopPack, itemRangeStart, itemRangeEnd, shopCurrency)
callClientFunction(player, "openShopBuy", player, shopPack, shopCurrency);
player:SendMessage(0x20, "", "shopPack: "..shopPack.." Range: "..itemRangeStart.."-"..itemRangeEnd);
while (true) do
buyResult, quantity = callClientFunction(player, "selectShopBuy", player);
if (buyResult == 0) then
callClientFunction(player, "closeShopBuy", player);
break;
else
if itemRangeStart and itemRangeEnd then
itemChosen = (itemRangeStart - 1) + buyResult;
if (((itemRangeStart-1) + itemChosen) < itemRangeStart) or (itemChosen > itemRangeEnd) then
player:SendMessage(0x20, "", "[ERROR] Client selected item exceeds the valid range.");
callClientFunction(player, "finishTalkTurn", player);
player:EndEvent();
return;
else
player:SendMessage(0x20, "", "Item chosen: " .. itemChosen .. " Quantity: ".. quantity);
--[[
TO-DO: Request item information from server table and throw result to purchaseItem()
requestItem = GetItemShopInfoThing(itemChosen);
purchaseItem(player, INVENTORY_NORMAL, requestItem.id, quantity, requestItem.quality, requestItem.price, shopCurrency);
--]]
end
end
end
end
end
function openSellMenu(player)
callClientFunction(player, "openShopSell", player);
while (true) do
sellResult, sellQuantity, sellState, unknown, sellItemSlot = callClientFunction(player, "selectShopSell", player);
if (sellResult == nil) then
callClientFunction(player, "closeShopSell", player);
break;
else
if sellState == 1 then
itemToSell = player:GetItemPackage(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
callClientFunction(player, "informSellPrice", 1, sellItemSlot, gItemPrice);
elseif sellState == nil then
sellItem(player, gItemSellId, sellQuantity, gItemQuality, gItemPrice, sellItemSlot-1, shopCurrency);
end
end
end
end

View File

@@ -0,0 +1,46 @@
--[[
OrdinaryRetainer Script
Functions:
eventTalkRetainerOther() -
eventTalkRetainerMenu(mode, hasPossessions) - Opens the main menu. If mode == 2, hide dismiss option.
eventTalkRetainerDismissal(hasPossessions) - Show dismiss confirmation.
eventTalkRetainerMannequin(0:enable/1:disable confirm) - Show bazaar modeling confirmation.
eventTalkRetainerItemTrade(operationCode) - Operate RetainerTradeWidget. Codes: 1 - Open, 2 - Select Mode, 3 - Close.
eventTalkRetainerItemList(operationCode) - Operate Bazaar Widget. Codes: 1 - Open, 2 - Select Mode, 3 - Close.
eventReturnResult(resultCode, ?) - Redraws the RetainerTrade UI.
sayToPlayer(actorClassId, messageType, argument) - Makes the retainer say a phrase to the player.
eventTalkFinish() - Stops npc from looking at player.
eventPlayerTurn(angle) - Turns player to angle.
--]]
require ("global")
require ("retainer")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, retainer, triggerName)
while (true) do
choice = callClientFunction(player, "eventTalkRetainerMenu", 1);
if (choice == 1) then
doItemTrade(player, retainer);
elseif (choice == 2) then
doBazaar(player, retainer);
elseif (choice == 7) then
callClientFunction(player, "eventTalkRetainerMannequin", 0);
elseif (choice == 5) then
player:DespawnMyRetainer();
else
break;
end
end
player:EndEvent();
end

175
Data/scripts/battlenpc.lua Normal file
View File

@@ -0,0 +1,175 @@
local initClassItems, initRaceItems;
function onBeginLogin(player)
--New character, set the initial quest
if (player:GetPlayTime(false) == 0) then
initialTown = player:GetInitialTown();
if (initialTown == 1 and player:HasQuest(110001) == false) then
player:AddQuest(110001);
player:SetHomePoint(1280001);
elseif (initialTown == 2 and player:HasQuest(110005) == false) then
player:AddQuest(110005);
player:SetHomePoint(1280061);
elseif (initialTown == 3 and player:HasQuest(110009) == false) then
player:AddQuest(110009);
player:SetHomePoint(1280031);
end
end
--For Opening. Set Director and reset position incase d/c
if (player:HasQuest(110001) == true and player.CurrentArea.ZoneId == 193) then
director = player:GetZone():CreateDirector("OpeningDirector", false);
player:AddDirector(director);
director:StartDirector(true);
player:SetLoginDirector(director);
player:KickEvent(director, "noticeEvent", true);
player.positionX = 0.016;
player.positionY = 10.35;
player.positionZ = -36.91;
player.rotation = 0.025;
player:GetQuest(110001):ClearQuestData();
player:GetQuest(110001):ClearQuestFlags();
elseif (player:HasQuest(110005) == true and player.CurrentArea.ZoneId == 166) then
director = player:GetZone():CreateDirector("OpeningDirector", false);
player:AddDirector(director);
director:StartDirector(false);
player:SetLoginDirector(director);
player:KickEvent(director, "noticeEvent", true);
player.positionX = 369.5434;
player.positionY = 4.21;
player.positionZ = -706.1074;
player.rotation = -1.26721;
player:GetQuest(110005):ClearQuestData();
player:GetQuest(110005):ClearQuestFlags();
elseif (player:HasQuest(110009) == true and player.CurrentArea.ZoneId == 184) then
--director = player:GetZone():CreateDirector("OpeningDirector", false);
--player:AddDirector(director);
--director:StartDirector(false);
--player:SetLoginDirector(director);
--player:KickEvent(director, "noticeEvent", true);
--
player.positionX = 5.364327;
player.positionY = 196.0;
player.positionZ = 133.6561;
player.rotation = -2.849384;
player:GetQuest(110009):ClearQuestData();
player:GetQuest(110009):ClearQuestFlags();
end
end
function onLogin(player)
if (player:GetPlayTime(false) == 0) then
player:SendMessage(0x1D,"",">PlayTime == 0, new player!");
initClassItems(player);
initRaceItems(player);
player:SavePlayTime();
end
end
function initClassItems(player)
local slotTable;
local invSlotTable;
--DoW
if (player.charaWork.parameterSave.state_mainSkill[0] == 2) then --PUG
player:GetItemPackage(0):AddItem({4020001, 8030701, 8050728, 8080601, 8090307});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 3) then --GLA
player:GetItemPackage(0):AddItem({4030010, 8031120, 8050245, 8080601, 8090307});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 4) then --MRD
player:GetItemPackage(0):AddItem({4040001, 8011001, 8050621, 8070346, 8090307});
player:GetEquipment():SetEquipment({0, 8, 12, 13, 15},{0, 1, 2, 3, 4});
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 7) then --ARC
player:GetItemPackage(0):AddItem({4070001, 8030601, 8050622, 8080601, 8090307});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 8) then --LNC
player:GetItemPackage(0):AddItem({4080201, 8030801, 8051015, 8080501, 8090307});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
--DoM
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 22) then --THM
player:GetItemPackage(0):AddItem({5020001, 8030245, 8050346, 8080346, 8090208});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 23) then --CNJ
player:GetItemPackage(0):AddItem({5030101, 8030445, 8050031, 8080246, 8090208});
player:GetEquipment():SetEquipment({0, 10, 12, 14, 15},{0, 1, 2, 3, 4});
--DoH
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 29) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 30) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 31) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 32) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 33) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 34) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 35) then --
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 36) then --
--DoL
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 39) then --MIN
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 40) then --BTN
elseif (player.charaWork.parameterSave.state_mainSkill[0] == 41) then --FSH
end
end
function initRaceItems(player)
if (player.playerWork.tribe == 1) then --Hyur Midlander Male
player:GetItemPackage(0):AddItem(8040001);
player:GetItemPackage(0):AddItem(8060001);
elseif (player.playerWork.tribe == 2) then --Hyur Midlander Female
player:GetItemPackage(0):AddItem(8040002);
player:GetItemPackage(0):AddItem(8060002);
elseif (player.playerWork.tribe == 3) then --Hyur Highlander Male
player:GetItemPackage(0):AddItem(8040003);
player:GetItemPackage(0):AddItem(8060003);
elseif (player.playerWork.tribe == 4) then --Elezen Wildwood Male
player:GetItemPackage(0):AddItem(8040004);
player:GetItemPackage(0):AddItem(8060004);
elseif (player.playerWork.tribe == 5) then --Elezen Wildwood Female
player:GetItemPackage(0):AddItem(8040006);
player:GetItemPackage(0):AddItem(8060006);
elseif (player.playerWork.tribe == 6) then --Elezen Duskwight Male
player:GetItemPackage(0):AddItem(8040005);
player:GetItemPackage(0):AddItem(8060005);
elseif (player.playerWork.tribe == 7) then --Elezen Duskwight Female
player:GetItemPackage(0):AddItem(8040007);
player:GetItemPackage(0):AddItem(8060007);
elseif (player.playerWork.tribe == 8) then --Lalafell Plainsfolk Male
player:GetItemPackage(0):AddItem(8040008);
player:GetItemPackage(0):AddItem(8060008);
elseif (player.playerWork.tribe == 9) then --Lalafell Plainsfolk Female
player:GetItemPackage(0):AddItem(8040010);
player:GetItemPackage(0):AddItem(8060010);
elseif (player.playerWork.tribe == 10) then --Lalafell Dunesfolk Male
player:GetItemPackage(0):AddItem(8040009);
player:GetItemPackage(0):AddItem(8060009);
elseif (player.playerWork.tribe == 11) then --Lalafell Dunesfolk Female
player:GetItemPackage(0):AddItem(8040011);
player:GetItemPackage(0):AddItem(8060011);
elseif (player.playerWork.tribe == 12) then --Miqo'te Seekers of the Sun
player:GetItemPackage(0):AddItem(8040012);
player:GetItemPackage(0):AddItem(8060012);
elseif (player.playerWork.tribe == 13) then --Miqo'te Seekers of the Moon
player:GetItemPackage(0):AddItem(8040013);
player:GetItemPackage(0):AddItem(8060013);
elseif (player.playerWork.tribe == 14) then --Roegadyn Sea Wolf
player:GetItemPackage(0):AddItem(8040014);
player:GetItemPackage(0):AddItem(8060014);
elseif (player.playerWork.tribe == 15) then --Roegadyn Hellsguard
player:GetItemPackage(0):AddItem(8040015);
player:GetItemPackage(0):AddItem(8060015);
end
player:GetEquipment():SetEquipment({9, 11},{5,6});
end

View File

@@ -0,0 +1,107 @@
CommandType =
{
None = 0,
AutoAttack = 1,
Weaponskill = 2,
Ability = 3,
Spell = 4
}
ActionType =
{
None = 0,
Physical = 1,
Magic = 2,
Heal = 3,
Status = 4
}
ActionProperty =
{
None = 0,
Physical = 1,
Magic = 2,
Heal = 4,
Status = 8,
Ranged = 16
}
DamageTakenType =
{
None,
Attack,
Magic,
Weaponskill,
Ability
}
HitDirection =
{
None = 0,
Front = 1,
Right = 2,
Rear = 4,
Left = 8
}
HitType =
{
Miss = 0,
Evade = 1,
Parry = 2,
Block = 3,
Resist = 4,
Hit = 5,
Crit = 6
}
TargetFindAOEType =
{
None = 0,
Circle = 1,
Cone = 2,
Box = 3
}
StatusEffectFlags =
{
None = 0,
--Loss flags - Do we need loseonattacking/caststart? Could just be done with activate flags
LoseOnDeath = bit32.lshift(1, 0), -- effects removed on death
LoseOnZoning = bit32.lshift(1, 1), -- effects removed on zoning
LoseOnEsuna = bit32.lshift(1, 2), -- effects which can be removed with esuna (debuffs)
LoseOnDispel = bit32.lshift(1, 3), -- some buffs which player might be able to dispel from mob
LoseOnLogout = bit32.lshift(1, 4), -- effects removed on logging out
LoseOnAttacking = bit32.lshift(1, 5), -- effects removed when owner attacks another entity
LoseOnCastStart = bit32.lshift(1, 6), -- effects removed when owner starts casting
LoseOnAggro = bit32.lshift(1, 7), -- effects removed when owner gains enmity (swiftsong)
LoseOnClassChange = bit32.lshift(1, 8), --Effect falls off whhen changing class
--Activate flags
ActivateOnCastStart = bit32.lshift(1, 9), --Activates when a cast starts.
ActivateOnCommandStart = bit32.lshift(1, 10), --Activates when a command is used, before iterating over targets. Used for things like power surge, excruciate.
ActivateOnCommandFinish = bit32.lshift(1, 11), --Activates when the command is finished, after all targets have been iterated over. Used for things like Excruciate and Resonance falling off.
ActivateOnPreactionTarget = bit32.lshift(1, 12), --Activates after initial rates are calculated for an action against owner
ActivateOnPreactionCaster = bit32.lshift(1, 13), --Activates after initial rates are calculated for an action by owner
ActivateOnDamageTaken = bit32.lshift(1, 14),
ActivateOnHealed = bit32.lshift(1, 15),
--Should these be rolled into DamageTaken?
ActivateOnMiss = bit32.lshift(1, 16), --Activates when owner misses
ActivateOnEvade = bit32.lshift(1, 17), --Activates when owner evades
ActivateOnParry = bit32.lshift(1, 18), --Activates when owner parries
ActivateOnBlock = bit32.lshift(1, 19), --Activates when owner evades
ActivateOnHit = bit32.lshift(1, 20), --Activates when owner hits
ActivateOnCrit = bit32.lshift(1, 21), --Activates when owner crits
--Prevent flags. Sleep/stun/petrify/etc combine these
PreventSpell = bit32.lshift(1, 22), -- effects which prevent using spells, such as silence
PreventWeaponSkill = bit32.lshift(1, 23), -- effects which prevent using weaponskills, such as pacification
PreventAbility = bit32.lshift(1, 24), -- effects which prevent using abilities, such as amnesia
PreventAttack = bit32.lshift(1, 25), -- effects which prevent basic attacks
PreventMovement = bit32.lshift(1, 26), -- effects which prevent movement such as bind, still allows turning in place
PreventTurn = bit32.lshift(1, 27), -- effects which prevent turning, such as stun
PreventUntarget = bit32.lshift(1, 28), -- effects which prevent changing targets, such as fixation
Stance = bit32.lshift(1, 29) -- effects that do not have a timer
}

View File

@@ -0,0 +1,19 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
local attackMagicHandlers = {
}
function onEventStarted(player, command, eventType, eventName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Ability(command.Id, targetActor);
player:endEvent();
end

View File

@@ -0,0 +1,5 @@
require("global")
function onEventStarted(player, command, eventType, eventName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
end

View File

@@ -0,0 +1,20 @@
require ("global")
--[[
ActivateCommand Script
Switches between active and passive mode states
--]]
function onEventStarted(player, command, eventType, eventName)
if (player.currentMainState == 0x0000) then
player.Engage(0, 0x0002);
elseif (player.currentMainState == 0x0002) then
player.Disengage(0x0000);
end
player:endEvent();
sendSignal("playerActive");
end;

View File

@@ -0,0 +1,20 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
local attackMagicHandlers = {
}
function onEventStarted(player, command, eventType, eventName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Ability(command.Id, targetActor);
player:endEvent();
end

View File

@@ -0,0 +1,19 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
local attackMagicHandlers = {
}
function onEventStarted(player, command, eventType, eventName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Cast(command.Id, targetActor);
player:endEvent();
end;

View File

@@ -0,0 +1,26 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
function onEventStarted(player, command, eventType, eventName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
--Are they in active mode?
if (player:GetState() != 2) then
player:SendGameMessage(GetWorldMaster(), 32503, 0x20);
player:endEvent();
return;
end
if not player.aiContainer.IsEngaged() then
player.Engage(targetActor);
end;
player.WeaponSkill(command.Id, targetActor);
player:endEvent();
end;

View File

@@ -0,0 +1,30 @@
--[[
BazaarCheckCommand Script
Handles what happens when you examine a player's bazaar
--]]
require ("global")
function onEventStarted(player, actor, eventType, eventName, name, arg1, arg2, arg3, bazaarActorId)
local bazaarActor = nil;
if (name ~= nil) then
bazaarActor = player.CurrentArea:FindPCInZone(name);
elseif (bazaarActorId ~= nil) then
bazaarActor = player.CurrentArea:FindActorInArea(bazaarActorId);
end
if (bazaarActor ~= nil) then
player:SendMessage(MESSAGE_TYPE_SYSTEM_ERROR, "", "Currently disabled due to freezing characters.");
--callClientFunction(player, "delegateCommand", GetStaticActor("BazaarCheckCommand"), "processChackBazaar");
else
--Show error
end
player:EndEvent();
end

Some files were not shown because too many files have changed in this diff Show More