947 Commits

Author SHA1 Message Date
Stephen Triche 612cfe22d9 Merged in TorqMySqlFix (pull request #78)
Addresses issues new people have been having running project on Windows 10 and Windows 11

Approved-by: Joe Lin
2024-12-12 03:36:08 +00:00
striche 1e311904cc Addressed issues where users on Windows 10 and Windows 11 were having issues running running the project.
1) Updated all projects to .NET Framework 4.7.2. This was a necessary prerequisite for the core fix.

2) The core fix is to upgrade the version of MySql.Data to address an error when opening connections. There is some kind of nuget issue with updating to the latest version (8.0.32) so fell back to updating to version 8.0.31. This also causes the addition of several all dependant libraries. Opted to just keep those at whatever version was specified by MySql.Data for now.

3) With the upgrade to MySql.Data, there is a behavioral change with the way the .Prepare statemenet works, and now it's required that parameters be added BEFORE calling .Prepare. So I've maded adjustments to the calls to .Prepare.
2023-02-04 16:35:15 -06:00
Robert Baker 8ceee35492 Batch script to copy all files for postbuild -- Reiichi001 2022-11-18 16:34:37 +00:00
Filip Maj 40b677f871 README.md edited online with Bitbucket 2022-11-18 16:31:52 +00:00
Robert Baker 57e7ee1894 Merged in Robert-Baker/importbat-had-a-line-missing-password-fi-1590334814488 (pull request #71)
import.bat had a line missing %PASSWORD% field for importing SQL files.

Approved-by: Filip Maj
2022-01-20 03:15:59 +00:00
PW Anon 61069e6d49 Merged in issue-21 (pull request #69)
Fix to Character Name Reservation

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


Approved-by: Filip Maj
2022-01-20 03:15:31 +00:00
Filip Maj 0521b167fb README.md edited online with Bitbucket 2021-03-24 19:58:16 +00: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
1843 changed files with 124403 additions and 64288 deletions
+215 -4
View File
@@ -1,4 +1,215 @@
FFXIVClassic Map Server/bin/Debug/packets/wireshark packets/ # Ignore files obtained from game client
FFXIVClassic Map Server/bin/ /data/staticactors.bin
FFXIVClassic Map Server/obj/ /data/packets/login/login*.bin
config.ini
## 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
+477
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);
}
}
}
@@ -1,13 +1,30 @@
using System; /*
using System.Collections.Generic; ===========================================================================
using System.Linq; Copyright (C) 2015-2019 Project Meteor Dev Team
using System.Text;
using System.Threading.Tasks;
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)] [global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class BitfieldLengthAttribute : Attribute public sealed class BitfieldLengthAttribute : Attribute
{ {
uint length; uint length;
@@ -19,7 +36,7 @@ namespace FFXIVClassic_Lobby_Server.common
public uint Length { get { return length; } } public uint Length { get { return length; } }
} }
static class PrimitiveConversion public static class PrimitiveConversion
{ {
public static UInt32 ToUInt32<T>(T t) where T : struct 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 // Calculate a bitmask of the desired length
long mask = 0; long mask = 0;
for (int i = 0; i < fieldLength; i++) for (int i = 0; i < fieldLength; i++)
mask |= 1 << i; mask |= 1L << i;
r |= ((UInt32)f.GetValue(t) & mask) << offset; r |= ((UInt32)f.GetValue(t) & mask) << offset;
@@ -75,4 +92,4 @@ namespace FFXIVClassic_Lobby_Server.common
return r; return r;
} }
} }
} }
@@ -1,10 +1,27 @@
using System; /*
using System.Collections.Generic; ===========================================================================
using System.Linq; Copyright (C) 2015-2019 Project Meteor Dev Team
using System.Text;
using System.Threading.Tasks;
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 public class Blowfish
{ {
@@ -287,7 +304,7 @@ namespace FFXIVClassic_Lobby_Server.common
public Blowfish(byte[] key) public Blowfish(byte[] key)
{ {
initializeBlowfish(key); InitializeBlowfish(key);
} }
public void Encipher(byte[] data, int offset, int length) 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 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)); 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 + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8); data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16); 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 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)); 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 + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8); data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16); data[i + 2] = (byte)(xl >> 16);
@@ -355,7 +372,7 @@ namespace FFXIVClassic_Lobby_Server.common
return y; return y;
} }
private void blowfish_encipher(ref UInt32 xl, ref UInt32 xr) private void BlowfishEncipher(ref UInt32 xl, ref UInt32 xr)
{ {
UInt32 temp; UInt32 temp;
Int32 i; 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; UInt32 temp;
Int32 i; Int32 i;
@@ -387,13 +404,13 @@ namespace FFXIVClassic_Lobby_Server.common
xl = xl ^ P[i]; xl = xl ^ P[i];
xr = F(xl) ^ xr; xr = F(xl) ^ xr;
/* Exchange xl and xr */ /* ExChange xl and xr */
temp = xl; temp = xl;
xl = xr; xl = xr;
xr = temp; xr = temp;
} }
/* Exchange xl and xr */ /* ExChange xl and xr */
temp = xl; temp = xl;
xl = xr; xl = xr;
xr = temp; xr = temp;
@@ -403,7 +420,7 @@ namespace FFXIVClassic_Lobby_Server.common
} }
private int initializeBlowfish(byte [] key) private int InitializeBlowfish(byte [] key)
{ {
Int16 i; Int16 i;
Int16 j; Int16 j;
@@ -437,7 +454,7 @@ namespace FFXIVClassic_Lobby_Server.common
for (i = 0; i < N + 2; i += 2) for (i = 0; i < N + 2; i += 2)
{ {
blowfish_encipher(ref datal, ref datar); BlowfishEncipher(ref datal, ref datar);
P[i] = datal; P[i] = datal;
P[i + 1] = datar; P[i + 1] = datar;
@@ -447,7 +464,7 @@ namespace FFXIVClassic_Lobby_Server.common
{ {
for (j = 0; j < 256; j += 2) 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] = datal;
S[i,j + 1] = datar; S[i,j + 1] = datar;
} }
+148
View File
@@ -0,0 +1,148 @@
<?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.7.2</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="BouncyCastle.Crypto, Version=1.9.0.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
<HintPath>..\packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="DotNetZip">
<HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf, Version=3.19.4.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.19.4\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="K4os.Compression.LZ4, Version=1.2.6.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
<HintPath>..\packages\K4os.Compression.LZ4.1.2.6\lib\net46\K4os.Compression.LZ4.dll</HintPath>
</Reference>
<Reference Include="K4os.Compression.LZ4.Streams, Version=1.2.6.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
<HintPath>..\packages\K4os.Compression.LZ4.Streams.1.2.6\lib\net46\K4os.Compression.LZ4.Streams.dll</HintPath>
</Reference>
<Reference Include="K4os.Hash.xxHash, Version=1.0.6.0, Culture=neutral, PublicKeyToken=32cd54395057cec3, processorArchitecture=MSIL">
<HintPath>..\packages\K4os.Hash.xxHash.1.0.6\lib\net46\K4os.Hash.xxHash.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=8.0.31.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.8.0.31\lib\net452\MySql.Data.dll</HintPath>
</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.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<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" />
<Reference Include="ZstdNet, Version=1.4.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.8.0.31\lib\net452\ZstdNet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BasePacket.cs" />
<Compile Include="Bitfield.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>
+179
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;
}
}
}
}
@@ -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")]
@@ -3,16 +3,16 @@
// ******************************* // *******************************
// *** (C)2009-2013 S.T.A. snc *** // *** (C)2009-2013 S.T.A. snc ***
// ******************************* // *******************************
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace STA.Settings namespace Meteor.Common
{ {
public class INIFile
internal class INIFile
{ {
#region "Declarations" #region "Declarations"
@@ -179,7 +179,7 @@ namespace STA.Settings
// *** Check if original file exists *** // *** Check if original file exists ***
bool OriginalFileExists = File.Exists(m_FileName); bool OriginalFileExists = File.Exists(m_FileName);
// *** Get temporary file name *** // *** get temporary file name ***
string TmpFileName = Path.ChangeExtension(m_FileName, "$n$"); string TmpFileName = Path.ChangeExtension(m_FileName, "$n$");
// *** Copy content of original file to temporary file, replace modified values *** // *** Copy content of original file to temporary file, replace modified values ***
@@ -199,7 +199,7 @@ namespace STA.Settings
// *** Open the original file *** // *** Open the original file ***
sr = new StreamReader(m_FileName); 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 s;
string SectionName; string SectionName;
string Key = null; string Key = null;
@@ -337,7 +337,7 @@ namespace STA.Settings
} }
// *** Read a value from local cache *** // *** 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 *** // *** Lazy loading ***
if (m_Lazy) if (m_Lazy)
@@ -380,7 +380,7 @@ namespace STA.Settings
Dictionary<string, string> Section; Dictionary<string, string> Section;
if (!m_Sections.TryGetValue(SectionName, out 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>(); Section = new Dictionary<string, string>();
m_Sections.Add(SectionName,Section); m_Sections.Add(SectionName,Section);
} }
@@ -474,7 +474,7 @@ namespace STA.Settings
return DefaultValue; 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)); string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
double Value; double Value;
@@ -519,7 +519,7 @@ namespace STA.Settings
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture)); 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)); SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
} }
+33
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();
}
}
+239
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
}
}
}
+487
View File
@@ -0,0 +1,487 @@
/*
===========================================================================
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)
break;
data[dataCounter] = (byte)(((array[i + bitCount] ? 1 : 0) << 7 - bitCount) | data[dataCounter]);
}
dataCounter++;
}
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)
{
return Encoding.ASCII.GetString(reader.ReadBytes(maxSize)).Trim(new[] { '\0' });
}
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
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;
}
}
}
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DotNetZip" version="1.10.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.19.4" targetFramework="net472" />
<package id="K4os.Compression.LZ4" version="1.2.6" targetFramework="net472" />
<package id="K4os.Compression.LZ4.Streams" version="1.2.6" targetFramework="net472" />
<package id="K4os.Hash.xxHash" version="1.0.6" targetFramework="net472" />
<package id="MySql.Data" version="8.0.31" targetFramework="net472" />
<package id="NLog" version="4.5.0" targetFramework="net451" />
<package id="Portable.BouncyCastle" version="1.9.0" targetFramework="net472" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net472" />
</packages>
+11
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
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=
+110
View File
@@ -0,0 +1,110 @@
@ECHO OFF
REM SETLOCAL
SET CWD = %~dp0
REM Echo Launch dir: "%~dp0"
REM Echo Current dir: "%CD%"
REM =============
REM COPY LOBBY CONFIG
REM =============
REM Required files: lobby_config.ini
SET /a foundlfolders = 0
if exist "%~dp0\..\Lobby Server\bin\Debug" (
SET /a foundlfolders = %foundlfolders% + 1
echo Found Lobby Debug build folder.
echo Copying lobby_config.ini if needed...
xcopy lobby_config.ini "%~dp0\..\Lobby Server\bin\Debug\" /d /y /q
)
if exist "%~dp0\..\Lobby Server\bin\Release" (
SET /a foundlfolders = %foundlfolders% + 1
echo Found Lobby Release build folder.
echo Copying lobby_config.ini if needed...
xcopy lobby_config.ini "%~dp0\..\Lobby Server\bin\Release\" /d /y /q
)
if %foundlfolders% LSS 1 (
echo Could not find debug or release folder for the Lobby server. Please compile the project first!
)
REM =============
REM COPY WORLD CONFIG
REM =============
REM Required files: world_config.ini
SET /a foundwfolders = 0
if exist "%~dp0\..\World Server\bin\Debug" (
SET /a foundwfolders = %foundwfolders% + 1
echo Found World Debug build folder.
echo Copying world_config.ini if needed...
xcopy world_config.ini "%~dp0\..\World Server\bin\Debug\" /d /y /q
)
if exist "%~dp0\..\World Server\bin\Release" (
SET /a foundwfolders = %foundwfolders% + 1
echo Found World Release build folder.
echo Copying world_config.ini if needed...
xcopy world_config.ini "%~dp0\..\World Server\bin\Release\" /d /y /q
)
if %foundwfolders% LSS 1 (
echo Could not find debug or release folder for the World server. Please compile the project first!
)
REM =============
REM COPY MAP CONFIG
REM =============
REM Required files: map_config.ini staticactors.bin scripts/
SET /a foundmfolders = 0
if exist "%~dp0\..\Map Server\bin\Debug" (
SET /a foundmfolders = %foundmfolders% + 1
echo Found Map Debug build folder.
echo Copying map_config.ini if needed...
xcopy map_config.ini "%~dp0\..\Map Server\bin\Debug\" /d /y /q
if exist staticactors.bin (
echo Copying staticactors.bin if needed...
xcopy staticactors.bin "%~dp0\..\Map Server\bin\Debug\" /d /y /q
) else (
echo Cannot copy the staticactors.bin file because it doesn't exist in data\
)
echo Copying scripts folder if needed...
xcopy scripts "%~dp0\..\Map Server\bin\Debug\scripts\" /e /d /y /s /q
)
if exist "%~dp0\..\Map Server\bin\Release" (
SET /a foundmfolders = %foundmfolders% + 1
echo Found Map Release build folder.
echo Copying map_config.ini if needed...
xcopy map_config.ini "%~dp0\..\Map Server\bin\Release\" /d /y /q
if exist staticactors.bin (
echo Copying staticactors.bin if needed...
xcopy staticactors.bin "%~dp0\..\Map Server\bin\Release\" /d /y /q
) else (
echo Cannot copy the staticactors.bin file because it doesn't exist in data\
)
echo Copying scripts folder if needed...
xcopy scripts "%~dp0\..\Map Server\bin\Release\scripts\" /e /d /y /s /q
)
if %foundmfolders% LSS 1 (
echo Could not find debug or release folder for the Map server. Please compile the project first!
)
Pause
+58
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
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
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
@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0, 0, 0;
end
@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return false, false, 0, 0, 0, 0;
end
@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0, 303, 10405;
end
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
@@ -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
@@ -0,0 +1,5 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
@@ -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
@@ -0,0 +1,152 @@
--[[
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, triggerName)
local npcCity = city[npc:GetActorClassId()] or 1;
local wardPlaceName = 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 questAreaName = 0; --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[4];
if (currZone == 133 or currZone == 230 or currZone == 155 or currZone == 206 or currZone == 175 or currZone == 209) then
exitPlaceName = 0; -- If in city, hide city menu option
elseif (currZone == 232 or currZone == 234 or currZone == 233) then
gcHQPlaceName = 0; -- If in GC Office, hide office menu option
end
choice = callClientFunction(player, "eventPushChoiceAreaOrQuest", exitPlaceName, wardPlaceName, gcHQPlaceName, questAreaName, showItemSearchCounter, itemSearchId);
while (true) do
if choice == wardPlaceName 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 == 0 or choice == -3) then -- Menu Closed
break;
end
choice = callClientFunction(player, "eventPushChoiceAreaOrQuest", exitPlaceName, wardPlaceName, gcHQPlaceName, questAreaName, showItemSearchCounter, itemSearchId);
end
player:EndEvent();
end
@@ -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
@@ -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
@@ -0,0 +1,23 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
choice = callClientFunction(player, "askLogout", player);
if (choice == 2) then
player:SetSleeping();
player:QuitGame();
elseif (choice == 3) then
player:SetSleeping();
player:Logout();
elseif (choice == 4) then
player:SendMessage(33, "", "Heck the bed");
end
player:EndEvent();
end
@@ -0,0 +1,25 @@
--[[
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)
choice = callClientFunction(player, "eventDoorMoveAsk");
if (choice == 1) then
end
player:EndEvent();
end
@@ -0,0 +1,16 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
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
@@ -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
@@ -0,0 +1,6 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
@@ -0,0 +1,13 @@
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, 5);
end
player:EndEvent();
end
@@ -0,0 +1,12 @@
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
end
player:EndEvent();
end
@@ -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
@@ -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
@@ -0,0 +1,19 @@
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
questNOC = GetStaticActor("Noc000");
if (npc:GetActorClassId() == 1200193) then
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskLimsa", nil, nil, nil);
elseif (npc:GetActorClassId() == 1200194) then
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskUldah", nil, nil, nil);
else
callClientFunction(player, "delegateEvent", player, questNOC, "pETaskBoardAskGridania", nil, nil, nil);
end
player:EndEvent();
end
@@ -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:GetZone():CreateGuildleveDirector(glId, difficulty, player);
player:AddDirector(director);
director:StartDirector(true, glId)
end
else
goto SELECT_LOOP;
end
end
end
@@ -0,0 +1,154 @@
--[[
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)
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:GetZone():CreateGuildleveDirector(glId, difficulty, player);
player:AddDirector(director);
director:StartDirector(true, glId);
end
else
goto SELECT_LOOP;
end
end
end
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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:SendGameMessageDisplayIDSender(npc, 6, MESSAGE_TYPE_SAY, npc.displayNameId);
player:EndEvent();
end
@@ -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
@@ -0,0 +1,119 @@
--[[
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
};
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}
};
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc, triggerName)
local curLevel = 20; -- TODO: pull from character
local hasIssuance = player:GetItemPackage(INVENTORY_KEYITEMS):HasItem(gcIssuances[npc:GetActorClassId()]);
local hasChocobo = player.hasChocobo;
if (hasChocobo == false) then -- Let GMs auto have the issuance for debugging
hasIssuance = true;
end
local hasFunds = (player:GetCurrentGil() >= rentalPrice);
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[npc:GetActorClassId()];
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[npc:GetActorClassId()], 1);
--Warp with the special chocobo warp mode.
mountChocobo(player);
GetWorldManager():DoZoneChange(player, cityExits[npc:GetActorClassId()][1], nil, 0, SPAWN_CHOCOBO_GET, cityExits[npc:GetActorClassId()][2], cityExits[npc:GetActorClassId()][3], cityExits[npc:GetActorClassId()][4], cityExits[npc:GetActorClassId()][5]);
end
elseif(menuChoice == 2) then -- Summon Bird
mountChocobo(player);
GetWorldManager():DoZoneChange(player, cityExits[npc:GetActorClassId()][1], nil, 0, SPAWN_NO_ANIM, cityExits[npc:GetActorClassId()][2], cityExits[npc:GetActorClassId()][3], cityExits[npc:GetActorClassId()][4], cityExits[npc:GetActorClassId()][5]);
elseif(menuChoice == 3) then -- Change Barding
callClientFunction(player, "eventTalkStepBreak", player);
elseif(menuChoice == 5) then -- Rent Bird
mountChocobo(player, true, 1);
GetWorldManager():DoZoneChange(player, cityExits[npc:GetActorClassId()][1], nil, 0, SPAWN_CHOCOBO_RENTAL, cityExits[npc:GetActorClassId()][2], cityExits[npc:GetActorClassId()][3], cityExits[npc:GetActorClassId()][4], cityExits[npc:GetActorClassId()][5]);
else
callClientFunction(player, "eventTalkStepBreak", player);
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, 5.0, 10.0, 10.0);
player:ChangeState(15);
end
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,120 @@
--[[
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() - Ends talk
--]]
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, "playereventTalkStepBreak");
player:EndEvent();
else
-- callClientFunction(player, "eventAfterWarpOtherZone", player); -- Commented out for now to prevent double fade-to-black for warp
player:EndEvent();
GetWorldManager():DoZoneChange(player, aethernet[city][choice].zone, nil, 0, 15, aethernet[city][choice].x, aethernet[city][choice].y, aethernet[city][choice].z, aethernet[city][choice].r);
end
end
player:EndEvent();
end
@@ -0,0 +1,3 @@
function init(npc)
return false, false, 0, 0;
end
@@ -0,0 +1,24 @@
--[[
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)
callClientFunction(player, "eventIn", player, false, nil, 5);
player:EndEvent();
end
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,38 @@
--[[
PopulacePassiveGLPublisher Script
Functions:
askOfferPack() - Show Classes
askOfferRank() - Show Ranks
askOfferQuest(player)
confirmOffer(nil, questId)
confirmMaxOffer()
talkOfferWelcome(actor, leveAllowances)
talkOfferDecide()
talkOfferMaxOver()
selectDiscardGuildleve(player)
confirmJournal()
askDiscardGuildleve()
confirmDiscardGuildleve(nil, questId)
askRetryRegionalleve(questId, leveAllowances)
finishTalkTurn()
--]]
require ("global")
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc)
callClientFunction(player, "talkOfferWelcome", player, 1);
player:EndEvent();
end
function onEventUpdate(player, npc, step, menuOptionSelected, lsName, lsCrest)
--callClientFunction(player, "askOfferQuest", player, 1000);
end
@@ -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
@@ -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
@@ -0,0 +1,84 @@
--[[
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
@@ -0,0 +1,13 @@
function init(npc)
return false, false, 0, 0;
end
function onEventStarted(player, npc)
player:SendMessage(0x20, "", "This PopulaceStandard actor has no event set. Actor Class Id: " .. tostring(npc:GetActorClassId()));
player:EndEvent();
end
function onEventUpdate(player, npc, blah, menuSelect)
player:EndEvent();
end
@@ -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
@@ -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
@@ -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
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:GetZoneID() == 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:GetZoneID() == 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:GetZoneID() == 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
+107
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
}
+19
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, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Ability(command.actorId, targetActor);
player:endEvent();
end
+5
View File
@@ -0,0 +1,5 @@
require("global")
function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
end
+20
View File
@@ -0,0 +1,20 @@
require ("global")
--[[
ActivateCommand Script
Switches between active and passive mode states
--]]
function onEventStarted(player, command, triggerName)
if (player.currentMainState == 0x0000) then
player.Engage(0, 0x0002);
elseif (player.currentMainState == 0x0002) then
player.Disengage(0x0000);
end
player:endEvent();
sendSignal("playerActive");
end;
+20
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, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Ability(command.actorId, targetActor);
player:endEvent();
end
+19
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, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8)
player.Cast(command.actorId, targetActor);
player:endEvent();
end;
@@ -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, triggerName, 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.actorId, targetActor);
player:endEvent();
end;
@@ -0,0 +1,30 @@
--[[
BazaarCheckCommand Script
Handles what happens when you examine a player's bazaar
--]]
require ("global")
function onEventStarted(player, actor, triggerName, name, arg1, arg2, arg3, bazaarActorId)
local bazaarActor = nil;
if (name ~= nil) then
bazaarActor = player:GetZone():FindPCInZone(name);
elseif (bazaarActorId ~= nil) then
bazaarActor = player:GetZone():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
@@ -0,0 +1,58 @@
--[[
BazaarDealCommand Script
Handles various bazaar transfer options
All bazaar args have a Reward (The item the person who fufills the request gets) and a Seek (The item the player wants, either gil or an item).
Args:
rewardItem: Item reference to what will be given to the buyer. If it's gil the itemID will be given instead. If offering an item to seek; reward/seek are combined and put here.
seekItem: Item reference to what the buyer will give us. If it's gil the itemID will be given instead,
bazaarMode: The tag value to set in the bazaar item's data.
arg1: Always nil
bazaarActor: The actor who owns this bazaar
rewardAmount: The amount of rewardItem the buyer will get.
seekAmount: The amount of seekItem we want.
--]]
require ("global")
function onEventStarted(player, actor, triggerName, rewardItem, seekItem, bazaarMode, arg1, bazaarActor, rewardAmount, seekAmount, arg2, arg3, type9ItemIds)
local rewarding = nil;
local seeking = nil;
--Handle special case for offering an item.
if (seekItem == nil) then
rewarding = player:GetItemPackage(rewardItem.offerPackageId):GetItemAtSlot(rewardItem.offerSlot);
seeking = player:GetItemPackage(rewardItem.seekPackageId):GetItemAtSlot(rewardItem.seekSlot);
end
--Handle Reward
if (rewarding == nil) then
if (type(rewardItem) == "number") then
rewarding = player:GetItemPackage(INVENTORY_CURRENCY):GetItemByCatelogId(rewardItem);
else
rewarding = player:GetItem(rewardItem);
end
end
--Handle Seek
if (seeking == nil) then
if (type(seekItem) == "number") then
seeking = player:GetItemPackage(INVENTORY_CURRENCY):GetItemByCatelogId(seekItem);
else
seeking = player:GetItem(seekItem);
end
end
result = GetWorldManager():AddToBazaar(player, rewarding, seeking, rewardAmount, seekAmount, bazaarMode);
player:EndEvent();
end
@@ -0,0 +1,55 @@
--[[
BazaarTradeCommand Script
Handles bazaar trade
All bazaar args have a Reward (The item the person who fufills the request gets) and a Seek (The item the player wants, either gil or an item).
--]]
--TODO REFACTOR
function onEventStarted(player, actor, triggerName, rewardItem, seekItemOrCost, seekAmount, arg1, bazaarActorId, rewardAmount, rewardItemId, nameIndex, arg2, type9ItemIds)
local originalReward = nil;
local originalSeek = nil;
local bazaarActor = nil;
--Get the bazaar actor
if (bazaarActorId ~= nil) then
bazaarActor = player:GetZone():FindActorInArea(bazaarActorId);
end
--Abort if no actor
if (bazaarActor == nil) then
player:SendGameMessage(player, worldMaster, 25111, 0x20);
player:EndEvent();
return;
end
--If seekItem is a number, we are buying an item (ExecuteBazaarBuy)
if (type(seekItemOrCost) == "number") then
if (player:GetCurrentGil() >= seekItemOrCost) then
if (GetWorldManager():BazaarBuyOperation(bazaarActor, player, bazaarActor:GetItem(rewardItem), rewardAmount, seekItemOrCost)) then
else
player:SendGameMessage(player, worldMaster, 25111, 0x20);
end
else
player:SendGameMessage(player, worldMaster, 40252, 0x20);
end
else --Else we are fufilling a sought out item (ExecuteBazaarSell)
local rewardItem = bazaarActor:GetItem(rewardItem);
local seekItem = player:GetItem(seekItemOrCost);
if (rewardItem ~= nil and seekItem ~= nil) then
if (GetWorldManager():BazaarSellOperation(bazaarActor, player, rewardItem, rewardAmount, seekItem, seekAmount)) then
else
player:SendGameMessage(player, worldMaster, 25111, 0x20);
end
else
end
end
player:EndEvent();
end
@@ -0,0 +1,22 @@
--[[
BazaarUndealCommand Script
Handles canceling bazaar items
25107 - Your bazaar is either full or already contains that unique item.
25111 - Unable to complete transaction.
25112 - You are unable to remove the item from your bazaar. You cannot hold any more items.
25113 - Offered and sought items cannot be identical.
25114 - Items in less than mint condition cannot be offered.
25115 - Items in less than mint condition cannot be placed in your bazaar.
--]]
function onEventStarted(player, actor, triggerName, rewardItem, seekItem, bazaarType, narg, bazaarActor, rewardAmount, seekAmount, narg, narg, type9ItemIds)
GetWorldManager():RemoveFromBazaar(player, player:GetItem(rewardItem));
player:EndEvent();
end
@@ -0,0 +1,23 @@
--[[
BonusPointCommand Script
Functions:
operateUI(pointsAvailable, pointsLimit, str, vit, dex, int, min, pie)
--]]
require ("global")
function onEventStarted(player, actor, triggerName)
--local points = player:GetAttributePoints();
--player:RunEventFunction("delegateCommand", actor, "operateUI", points.available, points.limit, points.inSTR, points.inVIT, points.inDEX, points.inINT, points.inMIN, points.inPIT);
result = callClientFunction(player, "delegateCommand", actor, "operateUI", 100, 100, 10, 10, 10, 10, 10, 10);
--Do Save
if (result == true) then
end
player:endEvent();
end
@@ -0,0 +1,6 @@
function onEventStarted(player, caller, commandRequest, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
player:SetCurrentJob(17);
player:EndEvent();
end
+19
View File
@@ -0,0 +1,19 @@
--[[
CheckCommand Script
Handles player examining someone
--]]
function onEventStarted(player, commandactor, triggerName, arg1, arg2, arg3, arg4, checkedActorId)
actor = player:GetActorInInstance(checkedActorId);
if (actor ~= nil) then
player:examinePlayer(actor);
end
player:EndEvent();
end
@@ -0,0 +1,49 @@
--[[
ChocoboRideCommand Script
Handles mounting and dismounting the Chocobo and Goobbue
--]]
function onEventStarted(player, actor, triggerName, isGoobbue)
if (player:GetState() == 0) then
worldMaster = GetWorldMaster();
if (isGoobbue ~= true) then
player:ChangeMusic(83);
player:SendGameMessage(player, worldMaster, 26001, 0x20);
player:SetMountState(1);
else
player:ChangeMusic(98);
player:SendGameMessage(player, worldMaster, 26019, 0x20);
player:SetMountState(2);
end
player:ChangeSpeed(0.0, 5.0, 10.0, 10.0);
player:ChangeState(15);
else
player:ChangeMusic(player:GetZone().bgmDay);
worldMaster = GetWorldMaster();
if (player.rentalExpireTime != 0) then
player:SendGameMessage(player, worldMaster, 26004, 0x20); --You dismount.
else
if (player:GetMountState() == 1) then
player:SendGameMessage(player, worldMaster, 26003, 0x20); --You dismount X.
else
player:SendGameMessage(player, worldMaster, 26021, 0x20); --You dismount your Gobbue.
end
end
player:SetMountState(0);
player:ChangeSpeed(0.0, 2.0, 5.0, 5.0)
player:ChangeState(0);
end
player:EndEvent();
end
@@ -0,0 +1,144 @@
require ("global")
--[[
CmnAttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
local function handleTEST(player)
end
local weaponskillHandlers = {
[0xA0F067F4] = nil,
[0xA0F067F5] = nil,
[0xA0F067F7] = nil,
[0xA0F067F8] = nil,
[0xA0F067FA] = nil,
[0xA0F067FB] = nil,
[0xA0F067FD] = nil,
[0xA0F067FE] = nil,
[0xA0F06800] = nil,
[0xA0F06801] = nil,
[0xA0F06802] = nil,
[0xA0F06804] = nil,
[0xA0F06805] = nil,
[0xA0F06806] = nil,
[0xA0F06808] = nil,
[0xA0F0680A] = nil,
[0xA0F0680B] = nil,
[0xA0F0680D] = nil,
[0xA0F0680E] = nil,
[0xA0F06810] = nil,
[0xA0F06812] = nil,
[0xA0F06814] = nil,
[0xA0F068A8] = nil,
[0xA0F068A9] = nil,
[0xA0F068AB] = nil,
[0xA0F068AC] = nil,
[0xA0F068AE] = nil,
[0xA0F068AF] = nil,
[0xA0F068B2] = nil,
[0xA0F068B3] = nil,
[0xA0F068B5] = nil,
[0xA0F068B7] = nil,
[0xA0F068B8] = nil,
[0xA0F068B9] = nil,
[0xA0F068BB] = nil,
[0xA0F068BC] = nil,
[0xA0F068BE] = nil,
[0xA0F068BF] = nil,
[0xA0F068C1] = nil,
[0xA0F068C3] = nil,
[0xA0F068C5] = nil,
[0xA0F0695C] = nil,
[0xA0F0695D] = nil,
[0xA0F0695E] = nil,
[0xA0F06960] = nil,
[0xA0F06961] = nil,
[0xA0F06963] = nil,
[0xA0F06964] = nil,
[0xA0F06966] = nil,
[0xA0F06967] = nil,
[0xA0F06968] = nil,
[0xA0F0696A] = nil,
[0xA0F0696B] = nil,
[0xA0F0696D] = nil,
[0xA0F0696E] = nil,
[0xA0F06970] = nil,
[0xA0F06971] = nil,
[0xA0F06973] = nil,
[0xA0F06974] = nil,
[0xA0F06976] = nil,
[0xA0F06978] = nil,
[0xA0F06B78] = nil,
[0xA0F06B79] = nil,
[0xA0F06B7B] = nil,
[0xA0F06B7C] = nil,
[0xA0F06B7E] = nil,
[0xA0F06B7F] = nil,
[0xA0F06B81] = nil,
[0xA0F06B82] = nil,
[0xA0F06B84] = nil,
[0xA0F06B85] = nil,
[0xA0F06B8A] = nil,
[0xA0F06B8C] = nil,
[0xA0F06B8E] = nil,
[0xA0F06B90] = nil,
[0xA0F06B91] = nil,
[0xA0F06B93] = nil,
[0xA0F06B95] = nil,
[0xA0F06B97] = nil,
[0xA0F06C2C] = nil,
[0xA0F06C2D] = nil,
[0xA0F06C2F] = nil,
[0xA0F06C31] = nil,
[0xA0F06C32] = nil,
[0xA0F06C34] = nil,
[0xA0F06C35] = nil,
[0xA0F06C36] = nil,
[0xA0F06C38] = nil,
[0xA0F06C39] = nil,
[0xA0F06C3B] = nil,
[0xA0F06C3C] = nil,
[0xA0F06C3E] = nil,
[0xA0F06C3F] = nil,
[0xA0F06C41] = nil,
[0xA0F06C43] = nil,
[0xA0F06C45] = nil,
[0xA0F06C47] = nil,
[0xA0F06C49] = nil,
[0xA0F06C4B] = nil,
[0xA0F06D94] = nil,
[0xA0F06D95] = nil,
[0xA0F06D96] = nil,
[0xA0F06F92] = nil,
[0xA0F06F93] = nil,
[0xA0F06F95] = nil,
[0xA0F06F96] = nil,
[0xA0F070E6] = nil,
[0xA0F070E7] = nil,
[0xA0F070E9] = nil,
[0xA0F070EA] = nil
}
function onEventStarted(player, command, triggerName)
--Are they in active mode?
if (player:GetState() != 2) then
player:SendGameMessage(GetWorldMaster(), 32503, 0x20);
player:endEvent();
return;
end
if (weaponskillHandlers[command.actorId] ~= nil) then
weaponskillHandlers[command.actorId](player);
else
player:SendMessage(0x20, "", "That weaponskill is not implemented yet.");
end
player:endEvent();
end

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