Compare commits

..

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

219
.gitignore vendored
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

View File

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

View File

@ -1,13 +1,30 @@
using System; /*
using System.Collections.Generic; ===========================================================================
using System.Linq; 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;

View File

@ -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;
} }

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>

View File

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

View File

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

View File

@ -3,16 +3,16 @@
// ******************************* // *******************************
// *** (C)2009-2013 S.T.A. snc *** // *** (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
Common Class Lib/Sql.cs Normal file
View File

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

View File

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

487
Common Class Lib/Utils.cs Normal file
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
Common Class Lib/Vector3.cs Normal file
View File

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

View File

@ -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>

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
Data/lobby_config.ini Normal file
View File

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

11
Data/map_config.ini Normal file
View File

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

110
Data/postbuild_copy.bat Normal file
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
Data/scripts/ability.lua Normal file
View File

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

@ -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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

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

View File

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

View File

@ -0,0 +1,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

View File

@ -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

View File

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

View File

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

View File

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

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

@ -0,0 +1,175 @@
local initClassItems, initRaceItems;
function onBeginLogin(player)
--New character, set the initial quest
if (player:GetPlayTime(false) == 0) then
initialTown = player:GetInitialTown();
if (initialTown == 1 and player:HasQuest(110001) == false) then
player:AddQuest(110001);
player:SetHomePoint(1280001);
elseif (initialTown == 2 and player:HasQuest(110005) == false) then
player:AddQuest(110005);
player:SetHomePoint(1280061);
elseif (initialTown == 3 and player:HasQuest(110009) == false) then
player:AddQuest(110009);
player:SetHomePoint(1280031);
end
end
--For Opening. Set Director and reset position incase d/c
if (player:HasQuest(110001) == true and player: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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,26 @@
require ("global")
require ("utils")
--[[
AttackWeaponSkill Script
Finds the correct weaponskill subscript to fire when a weaponskill actor is activated.
--]]
function onEventStarted(player, command, 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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,6 @@
function onEventStarted(player, caller, commandRequest, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
player:SetCurrentJob(17);
player:EndEvent();
end

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

View File

@ -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

View File

@ -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