mirror of
https://github.com/ProjectSWGCore/Holocore.git
synced 2026-10-12 02:13:42 -04:00
@@ -73,6 +73,7 @@ dependencies {
|
||||
|
||||
utilityCompile project(':pswgcommon')
|
||||
utilityCompile sourceSets.main.output
|
||||
utilityCompile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: '1.3.50'
|
||||
utilityCompile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
|
||||
utilityCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.6.3'
|
||||
utilityCompile group: 'me.joshlarson', name: "fast-json", version: '3.0.0'
|
||||
|
||||
+1
-1
Submodule pswgcommon updated: e34be46179...9c041be3ef
+1565
-1535
File diff suppressed because it is too large
Load Diff
@@ -1075,33 +1075,6 @@ item_ithorian_gloves_02_01 object/tangible/wearables/ithorian/ith_gloves_s02.iff
|
||||
item_ithorian_pants_02_01 object/tangible/wearables/ithorian/ith_pants_s19.iff wearable Issued Ithorian Pants 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 agility_modified=3 -1 6 63 -1 45 0 0 npe clothing
|
||||
item_ithorian_shirt_02_01 object/tangible/wearables/ithorian/ith_shirt_s09.iff wearable Issued Ithorian Shirt 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 agility_modified=3 -1 31 63 -1 45 0 0 npe clothing
|
||||
item_ithorian_vest_02_01 object/tangible/wearables/ithorian/ith_vest_s02.iff wearable Issued Ithorian Vest 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 agility_modified=3 -1 0 63 -1 45 0 0 npe clothing
|
||||
item_jedi_robe_04_01 object/tangible/wearables/robe/robe_s05.iff wearable Cloak of the Kursk 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=50,precision_modified=80 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_04_02 object/tangible/wearables/robe/robe_s05.iff wearable Robes of the Storm Caller 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=50,strength_modified=80 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_04_03 object/tangible/wearables/robe/robe_s05_h1.iff wearable Jedi Knight Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=80,agility_modified=5,strength_modified=50,precision_modified=50 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_04_04 object/tangible/wearables/robe/robe_s05_h1.iff wearable Jedi Knight Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=80,agility_modified=5,luck_modified=50,precision_modified=50 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_06_01 object/tangible/wearables/robe/robe_s05_h1.iff wearable Jedi Master Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=100,strength_modified=100,luck_modified=100,precision_modified=100 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_06_02 object/tangible/wearables/robe/robe_s05_h1.iff wearable Jedi Master Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=100,strength_modified=100,luck_modified=100,precision_modified=100 -1 -1 -1 -1 7500 0 0 ToW expansion
|
||||
item_jedi_robe_06_03 object/tangible/wearables/robe/robe_s33_h1.iff wearable Shatterpoint Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=135,agility_modified=170,strength_modified=170,luck_modified=170,expertise_damage_weapon_9=4,expertise_damage_weapon_10=4,expertise_damage_weapon_11=4 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_06_04 object/tangible/wearables/robe/robe_s32_h1.iff wearable Cloak of Hate 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=135,agility_modified=170,luck_modified=170,precision_modified=170,expertise_damage_line_fs_ae_dm_cc=4 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_06_05 object/tangible/wearables/robe/robe_s33.iff wearable Shatterpoint Cloak 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=135,agility_modified=135,strength_modified=135,luck_modified=135,expertise_damage_weapon_9=4,expertise_damage_weapon_10=4,expertise_damage_weapon_11=4 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_06_06 object/tangible/wearables/robe/robe_s32.iff wearable Cloak of Hate 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=135,agility_modified=135,luck_modified=135,precision_modified=135,expertise_damage_line_fs_ae_dm_cc=4 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_dark_03_01 object/tangible/wearables/robe/robe_jedi_dark_s01.iff wearable Acolyte Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=100,precision_modified=100 -1 -1 -1 -1 3500 0 0
|
||||
item_jedi_robe_dark_03_02 object/tangible/wearables/robe/robe_jedi_dark_s02.iff wearable Apprentice Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=145,precision_modified=145 -1 -1 -1 -1 6000 0 0
|
||||
item_jedi_robe_dark_03_03 object/tangible/wearables/robe/robe_jedi_dark_s02.iff wearable Jedi Knight Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=185,luck_modified=185,precision_modified=185 -1 -1 -1 -1 7700 0 0
|
||||
item_jedi_robe_dark_04_01 object/tangible/wearables/robe/robe_jedi_dark_s01.iff wearable Dark Jedi Knight Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_dark_04_02 object/tangible/wearables/robe/robe_jedi_dark_s02.iff wearable Dark Jedi Enforcer Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_dark_04_03 object/tangible/wearables/robe/robe_jedi_dark_s03.iff wearable Dark Jedi Templar Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_dark_04_04 object/tangible/wearables/robe/robe_jedi_dark_s04.iff wearable Elder Jedi Oppressor Robe 1 1000 0 0 0 0 0 0 0 0 0 0 proc_old_dark_jedi_gift 0 0 0 appearance/pt_heal.prt 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=250,luck_modified=250,precision_modified=250 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_dark_04_05 object/tangible/wearables/robe/robe_jedi_dark_s05.iff wearable Dark Jedi Council Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_light_03_01 object/tangible/wearables/robe/robe_jedi_light_s01.iff wearable Acolyte Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=100,strength_modified=100 -1 -1 -1 -1 3500 0 0
|
||||
item_jedi_robe_light_03_02 object/tangible/wearables/robe/robe_jedi_light_s02.iff wearable Apprentice Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=145,strength_modified=145 -1 -1 -1 -1 6000 0 0
|
||||
item_jedi_robe_light_03_03 object/tangible/wearables/robe/robe_jedi_light_s02.iff wearable Jedi Knight Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=185,agility_modified=185,strength_modified=185 -1 -1 -1 -1 7700 0 0
|
||||
item_jedi_robe_light_04_01 object/tangible/wearables/robe/robe_jedi_light_s01.iff wearable Jedi Knight Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_light_04_02 object/tangible/wearables/robe/robe_jedi_light_s02.iff wearable Jedi Sentinel Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_light_04_03 object/tangible/wearables/robe/robe_jedi_light_s03.iff wearable Jedi Consular Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_light_04_04 object/tangible/wearables/robe/robe_jedi_light_s04.iff wearable Elder Jedi Arbiter Robe 1 1000 0 0 0 0 0 0 0 0 0 0 proc_old_light_jedi_gift 0 0 0 appearance/pt_heal.prt 0 0 0 0 80 force_sensitive 1 1 1 1 1 0 0 90001 0 0 constitution_modified=250,agility_modified=250,strength_modified=250 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_light_04_05 object/tangible/wearables/robe/robe_jedi_light_s05.iff wearable Jedi Council Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_jedi_robe_padawan_04_01 object/tangible/wearables/robe/robe_jedi_padawan_generic.iff wearable Padawan Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 90001 0 0 agility_modified=21 -1 -1 -1 -1 0 0 0
|
||||
item_lifeday_09_jacket_01 object/tangible/wearables/jacket/jacket_lifeday_09_01.iff wearable Life Day Jacket 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_lifeday_09_jacket_02 object/tangible/wearables/jacket/jacket_lifeday_09_02.iff wearable Holiday Jacket 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_lifeday_gift_04_13 object/tangible/wearables/necklace/necklace_lifeday.iff wearable Wookiee Life Day Necklace 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
@@ -1151,8 +1124,6 @@ item_npe_bracelet_melee_defense_01_01 object/tangible/wearables/bracelet/bracele
|
||||
item_npe_bracelet_rng_defense_01_01 object/tangible/wearables/bracelet/bracelet_s06_r.iff wearable Warped Soldier's Bracelet 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 appearance/pt_heal.prt 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 agility_modified=3 -1 -1 -1 -1 200 0 0
|
||||
item_npe_bracelet_ter_neg_01_01 object/tangible/wearables/bracelet/bracelet_s02_r.iff wearable Warped Traveler's Bracelet 1 1000 0 0 0 0 0 0 0 0 0 0 trivialSlopeMove 0 0 0 appearance/pt_heal.prt 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 -1 -1 -1 -1 200 0 0
|
||||
item_npe_bracelet_unarmed_damage_01_01 object/tangible/wearables/bracelet/bracelet_s03_r.iff wearable Warped Strongman's Bracer 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 appearance/pt_heal.prt 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 strength_modified=3 -1 -1 -1 -1 200 0 0
|
||||
item_npe_fs_robe_02_01 object/tangible/wearables/robe/robe_jedi_padawan_generic.iff wearable Padawan Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 force_sensitive 1 1 1 1 1 0 0 0 0 0 agility_modified=10 -1 -1 -1 -1 0 0 0
|
||||
item_npe_fs_robe_02_02 object/tangible/wearables/robe/robe_jedi_padawan_generic.iff wearable Initiate's Robe 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 force_sensitive 1 1 1 1 1 0 0 0 0 0 constitution_modified=21 -1 -1 -1 -1 1250 0 0
|
||||
item_npe_hunting_necklace_01_01 object/tangible/wearables/necklace/necklace_s01.iff wearable Hunting Necklace 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 luck_modified=3 -1 -1 -1 -1 250 0 0
|
||||
item_npe_inaldras_bracelet_01_01 object/tangible/wearables/bracelet/bracelet_s04_r.iff wearable Inaldra's Bracelet 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 agility_modified=3 -1 -1 -1 -1 250 0 0
|
||||
item_npe_medic_bracelet_01_01 object/tangible/wearables/bracelet/bracelet_s06_r.iff wearable Polis Massan Bracelet 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 stamina_modified=2 -1 -1 -1 -1 250 0 0
|
||||
@@ -1659,4 +1630,4 @@ item_clothing_wookiee_shoulder_pad_01_02 object/tangible/wearables/wookiee/wke_s
|
||||
item_clothing_wookiee_skirt_01_01 object/tangible/wearables/wookiee/wke_skirt_s01.iff wearable Decorative Waist Wrap 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_clothing_wookiee_skirt_01_02 object/tangible/wearables/wookiee/wke_skirt_s02.iff wearable Sigiled Waist Wrap 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_clothing_wookiee_skirt_01_03 object/tangible/wearables/wookiee/wke_skirt_s03.iff wearable Weighted Waist Wrap 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_clothing_wookiee_skirt_01_04 object/tangible/wearables/wookiee/wke_skirt_s04.iff wearable Simple Waist Wrap 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
item_clothing_wookiee_skirt_01_04 object/tangible/wearables/wookiee/wke_skirt_s04.iff wearable Simple Waist Wrap 1 1000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 -1 -1 -1 -1 0 0 0
|
||||
+13
-39
@@ -1,62 +1,36 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.holocore.intents.gameplay.player.experience.skills;
|
||||
* along with Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
package com.projectswg.holocore.intents.gameplay.player.experience.skills
|
||||
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
|
||||
import me.joshlarson.jlcommon.control.Intent;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
|
||||
import me.joshlarson.jlcommon.control.Intent
|
||||
|
||||
public class SkillModIntent extends Intent {
|
||||
class SkillModIntent(val skillModName: String, val adjustBase: Int, val adjustModifier: Int, vararg val affectedCreatures: CreatureObject) : Intent() {
|
||||
|
||||
private final String skillModName;
|
||||
private final int adjustBase;
|
||||
private final int adjustModifier;
|
||||
private final CreatureObject[] affectedCreatures;
|
||||
|
||||
public SkillModIntent(String skillModName, int adjustBase, int adjustModifier, CreatureObject... affectedCreatures) {
|
||||
this.skillModName = skillModName;
|
||||
this.adjustBase = adjustBase;
|
||||
this.adjustModifier = adjustModifier;
|
||||
this.affectedCreatures = affectedCreatures;
|
||||
}
|
||||
|
||||
public int getAdjustModifier() {
|
||||
return adjustModifier;
|
||||
}
|
||||
|
||||
public int getAdjustBase() {
|
||||
return adjustBase;
|
||||
}
|
||||
|
||||
public String getSkillModName() {
|
||||
return skillModName;
|
||||
}
|
||||
|
||||
public CreatureObject[] getAffectedCreatures() {
|
||||
return affectedCreatures;
|
||||
}
|
||||
override fun toString() = "SkillModIntent['$skillModName' base=$adjustBase mod=$adjustModifier creatures=${affectedCreatures.toList()}]"
|
||||
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.holocore.intents.support.objects.swg;
|
||||
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
|
||||
import me.joshlarson.jlcommon.control.Intent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ContainerTransferIntent extends Intent {
|
||||
|
||||
private SWGObject obj;
|
||||
private SWGObject container;
|
||||
private SWGObject oldContainer;
|
||||
|
||||
public ContainerTransferIntent(@NotNull SWGObject obj, @Nullable SWGObject oldContainer, @Nullable SWGObject container) {
|
||||
this.obj = obj;
|
||||
this.oldContainer = oldContainer;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SWGObject getObject() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SWGObject getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SWGObject getOldContainer() {
|
||||
return oldContainer;
|
||||
}
|
||||
|
||||
public static void broadcast(@NotNull SWGObject obj, @Nullable SWGObject oldContainer, @Nullable SWGObject newContainer) {
|
||||
new ContainerTransferIntent(obj, oldContainer, newContainer).broadcast();
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
package com.projectswg.holocore.intents.support.objects.swg
|
||||
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
|
||||
import me.joshlarson.jlcommon.control.Intent
|
||||
|
||||
class ContainerTransferIntent(val `object`: SWGObject, val oldContainer: SWGObject?, val oldArrangement: Int, val container: SWGObject?, val arrangement: Int) : Intent() {
|
||||
|
||||
/** Alias for kotlin code, allowed as a stylistic choice */
|
||||
val obj: SWGObject
|
||||
get() = `object`
|
||||
|
||||
override fun toString() = "ContainerTransferIntent[obj=$`object` old=$oldArrangement/$oldContainer new=$arrangement/$container]"
|
||||
|
||||
companion object {
|
||||
|
||||
fun broadcast(obj: SWGObject, oldContainer: SWGObject?, oldArrangement: Int, newContainer: SWGObject?, arrangement: Int) {
|
||||
ContainerTransferIntent(obj, oldContainer, oldArrangement, newContainer, arrangement).broadcast()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.holocore.resources.gameplay.crafting.resource.galactic;
|
||||
|
||||
import com.projectswg.common.data.location.Terrain;
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.storage.GalacticResourceContainer;
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.raw.RawResource;
|
||||
import com.projectswg.holocore.resources.support.data.namegen.SWGNameGenerator;
|
||||
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
|
||||
import com.projectswg.holocore.resources.support.data.server_info.mongodb.PswgDatabase;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class GalacticResourceSpawner {
|
||||
|
||||
private static final Terrain [] ALL_PLANETS = new Terrain[] {
|
||||
Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR,
|
||||
Terrain.ENDOR, Terrain.KASHYYYK_MAIN, Terrain.LOK,
|
||||
Terrain.NABOO, Terrain.RORI, Terrain.TALUS,
|
||||
Terrain.TATOOINE, Terrain.YAVIN4, Terrain.MUSTAFAR
|
||||
};
|
||||
|
||||
private static final Terrain [] BASE_PLANETS = new Terrain[] {
|
||||
Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR,
|
||||
Terrain.ENDOR, Terrain.LOK, Terrain.NABOO,
|
||||
Terrain.RORI, Terrain.TALUS, Terrain.TATOOINE,
|
||||
Terrain.YAVIN4
|
||||
};
|
||||
|
||||
private final Random random;
|
||||
private final AtomicLong resourceIdMax;
|
||||
private final SWGNameGenerator resourceNameGenerator;
|
||||
|
||||
public GalacticResourceSpawner() {
|
||||
this.random = new Random();
|
||||
this.resourceNameGenerator = new SWGNameGenerator();
|
||||
this.resourceIdMax = new AtomicLong(0);
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
loadResources();
|
||||
updateAllResources();
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
saveResources();
|
||||
}
|
||||
|
||||
public void updateAllResources() {
|
||||
updateSpawns();
|
||||
updateUnusedPools();
|
||||
}
|
||||
|
||||
private void loadResources() {
|
||||
long startTime = StandardLog.onStartLoad("galactic resources");
|
||||
int resourceCount = 0;
|
||||
for (GalacticResource resource : PswgDatabase.INSTANCE.getResources().getResources()) {
|
||||
GalacticResourceContainer.getContainer().addGalacticResource(resource);
|
||||
if (resource.getId() > resourceIdMax.get())
|
||||
resourceIdMax.set(resource.getId());
|
||||
resourceCount++;
|
||||
}
|
||||
StandardLog.onEndLoad(resourceCount, "galactic resources", startTime);
|
||||
}
|
||||
|
||||
private void saveResources() {
|
||||
GalacticResourceLoader loader = new GalacticResourceLoader();
|
||||
loader.saveResources(GalacticResourceContainer.getContainer().getAllResources());
|
||||
PswgDatabase.INSTANCE.getResources().setResources(GalacticResourceContainer.getContainer().getAllResources());
|
||||
}
|
||||
|
||||
private void updateUnusedPools() {
|
||||
List<RawResource> rawResources = GalacticResourceContainer.getContainer().getRawResources();
|
||||
for (RawResource raw : rawResources) {
|
||||
if (raw.getMaxPools() == 0)
|
||||
continue;
|
||||
updateUnusedResourcePool(raw);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUnusedResourcePool(RawResource raw) {
|
||||
int spawned = GalacticResourceContainer.getContainer().getSpawnedGalacticResources(raw);
|
||||
int minTypes = raw.getMinTypes();
|
||||
int maxTypes = raw.getMaxTypes();
|
||||
if (spawned >= minTypes)
|
||||
return; // Only respawn once total number spawned in goes below minTypes
|
||||
int targetTypes = calculateTargetTypes(minTypes, maxTypes);
|
||||
for (int i = spawned; i < targetTypes; i++) {
|
||||
createNewResourceWithSpawns(raw);
|
||||
}
|
||||
}
|
||||
|
||||
private int calculateTargetTypes(int minTypes, int maxTypes) {
|
||||
double x = random.nextDouble();
|
||||
return (int) (x * x * (maxTypes - minTypes)) + minTypes;
|
||||
}
|
||||
|
||||
private void createNewResourceWithSpawns(RawResource raw) {
|
||||
int targetSpawns = random.nextInt(raw.getMaxPools() - raw.getMinPools() + 1) + raw.getMinPools();
|
||||
GalacticResource resource = createNewResource(raw);
|
||||
Terrain restricted = getRestrictedResource(raw);
|
||||
if (restricted == null) {
|
||||
for (Terrain terrain : BASE_PLANETS) {
|
||||
for (int i = 0; i < targetSpawns; i++) {
|
||||
createNewSpawn(resource, terrain);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < targetSpawns; i++) {
|
||||
createNewSpawn(resource, restricted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GalacticResource createNewResource(RawResource raw) {
|
||||
long newId = resourceIdMax.incrementAndGet();
|
||||
GalacticResource resource;
|
||||
do {
|
||||
String newName = resourceNameGenerator.generateName("resources");
|
||||
resource = new GalacticResource(newId, newName, raw.getId());
|
||||
resource.setRawResource(raw);
|
||||
} while (!GalacticResourceContainer.getContainer().addGalacticResource(resource));
|
||||
return resource;
|
||||
}
|
||||
|
||||
private void createNewSpawn(GalacticResource resource, Terrain terrain) {
|
||||
GalacticResourceSpawn spawn = new GalacticResourceSpawn(resource.getId());
|
||||
spawn.setRandomValues(terrain);
|
||||
resource.addSpawn(spawn);
|
||||
}
|
||||
|
||||
private void updateSpawns() {
|
||||
List<GalacticResource> resources = GalacticResourceContainer.getContainer().getAllResources();
|
||||
for (GalacticResource resource : resources) {
|
||||
List<GalacticResourceSpawn> spawns = resource.getSpawns();
|
||||
if (spawns.isEmpty())
|
||||
continue;
|
||||
List<GalacticResourceSpawn> expired = spawns.stream().filter(GalacticResourceSpawn::isExpired).collect(toList());
|
||||
expired.forEach(resource::removeSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
private Terrain getRestrictedResource(RawResource resource) {
|
||||
String key = resource.getName().getKey();
|
||||
if (key.length() >= 2 && Character.isDigit(key.charAt(key.length()-1)) && key.charAt(key.length()-2) == '_')
|
||||
key = key.substring(0, key.lastIndexOf('_'));
|
||||
for (Terrain test : ALL_PLANETS) {
|
||||
if (key.endsWith(test.getName()))
|
||||
return test;
|
||||
}
|
||||
if (key.endsWith("kashyyyk")) // special case because kashyyyk = kashyyyk_main
|
||||
return Terrain.KASHYYYK_MAIN;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
package com.projectswg.holocore.resources.gameplay.crafting.resource.galactic
|
||||
|
||||
import com.projectswg.common.data.location.Terrain
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.storage.GalacticResourceContainer
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.raw.RawResource
|
||||
import com.projectswg.holocore.resources.support.data.namegen.SWGNameGenerator
|
||||
import com.projectswg.holocore.resources.support.data.server_info.StandardLog
|
||||
import com.projectswg.holocore.resources.support.data.server_info.mongodb.PswgDatabase
|
||||
import me.joshlarson.jlcommon.log.Log
|
||||
import java.util.concurrent.ThreadLocalRandom
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import java.util.function.Consumer
|
||||
import java.util.stream.Collectors.toList
|
||||
|
||||
class GalacticResourceSpawner {
|
||||
|
||||
private val resourceIdMax = AtomicLong(0)
|
||||
private val resourceNameGenerator = SWGNameGenerator()
|
||||
|
||||
fun initialize() {
|
||||
loadResources()
|
||||
updateAllResources()
|
||||
}
|
||||
|
||||
fun terminate() {
|
||||
saveResources()
|
||||
}
|
||||
|
||||
fun updateAllResources() {
|
||||
updateSpawns()
|
||||
updateUnusedPools()
|
||||
}
|
||||
|
||||
private fun loadResources() {
|
||||
val startTime = StandardLog.onStartLoad("galactic resources")
|
||||
var resourceCount = 0
|
||||
for (resource in PswgDatabase.resources.resources) {
|
||||
GalacticResourceContainer.addGalacticResource(resource)
|
||||
if (resource.id > resourceIdMax.get())
|
||||
resourceIdMax.set(resource.id)
|
||||
resourceCount++
|
||||
}
|
||||
StandardLog.onEndLoad(resourceCount, "galactic resources", startTime)
|
||||
}
|
||||
|
||||
private fun saveResources() {
|
||||
val loader = GalacticResourceLoader()
|
||||
loader.saveResources(GalacticResourceContainer.allResources)
|
||||
PswgDatabase.resources.resources = GalacticResourceContainer.allResources
|
||||
}
|
||||
|
||||
private fun updateUnusedPools() {
|
||||
val rawResources = GalacticResourceContainer.rawResources
|
||||
for (raw in rawResources) {
|
||||
if (raw.maxPools == 0)
|
||||
continue
|
||||
updateUnusedResourcePool(raw)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUnusedResourcePool(raw: RawResource) {
|
||||
val spawned = GalacticResourceContainer.getSpawnedGalacticResources(raw)
|
||||
val minTypes = raw.minTypes
|
||||
val maxTypes = raw.maxTypes
|
||||
if (spawned >= minTypes)
|
||||
return // Only respawn once total number spawned in goes below minTypes
|
||||
val targetTypes = calculateTargetTypes(minTypes, maxTypes)
|
||||
for (i in spawned until targetTypes) {
|
||||
createNewResourceWithSpawns(raw)
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateTargetTypes(minTypes: Int, maxTypes: Int): Int {
|
||||
val x = ThreadLocalRandom.current().nextDouble()
|
||||
return (x * x * (maxTypes - minTypes).toDouble()).toInt() + minTypes
|
||||
}
|
||||
|
||||
private fun createNewResourceWithSpawns(raw: RawResource) {
|
||||
val targetSpawns = ThreadLocalRandom.current().nextInt(raw.minPools, raw.maxPools+1)
|
||||
val resource = createNewResource(raw)
|
||||
val restricted = getRestrictedResource(raw)
|
||||
if (restricted == null) {
|
||||
for (terrain in BASE_PLANETS) {
|
||||
for (i in 0 until targetSpawns) {
|
||||
createNewSpawn(resource, terrain)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i in 0 until targetSpawns) {
|
||||
createNewSpawn(resource, restricted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNewResource(raw: RawResource): GalacticResource {
|
||||
val newId = resourceIdMax.incrementAndGet()
|
||||
var resource: GalacticResource
|
||||
do {
|
||||
val newName = resourceNameGenerator.generateName("resources")
|
||||
resource = GalacticResource(newId, newName, raw.id)
|
||||
resource.rawResource = raw
|
||||
Log.t("Generating new resource: $resource $raw")
|
||||
} while (!GalacticResourceContainer.addGalacticResource(resource))
|
||||
return resource
|
||||
}
|
||||
|
||||
private fun createNewSpawn(resource: GalacticResource, terrain: Terrain) {
|
||||
val spawn = GalacticResourceSpawn(resource.id)
|
||||
spawn.setRandomValues(terrain)
|
||||
resource.addSpawn(spawn)
|
||||
}
|
||||
|
||||
private fun updateSpawns() {
|
||||
val resources = GalacticResourceContainer.allResources
|
||||
for (resource in resources) {
|
||||
val spawns = resource.spawns
|
||||
if (spawns.isEmpty())
|
||||
continue
|
||||
val expired = spawns.stream().filter { it.isExpired }.collect(toList())
|
||||
expired.forEach(Consumer<GalacticResourceSpawn> { resource.removeSpawn(it) })
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRestrictedResource(resource: RawResource): Terrain? {
|
||||
var key = resource.name.key
|
||||
if (key.length >= 2 && Character.isDigit(key[key.length - 1]) && key[key.length - 2] == '_')
|
||||
key = key.substring(0, key.lastIndexOf('_'))
|
||||
for (test in ALL_PLANETS) {
|
||||
if (key.endsWith(test.getName()))
|
||||
return test
|
||||
}
|
||||
return if (key.endsWith("kashyyyk")) Terrain.KASHYYYK_MAIN else null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val ALL_PLANETS = arrayOf(Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR, Terrain.ENDOR, Terrain.KASHYYYK_MAIN, Terrain.LOK, Terrain.NABOO, Terrain.RORI, Terrain.TALUS, Terrain.TATOOINE, Terrain.YAVIN4, Terrain.MUSTAFAR)
|
||||
|
||||
private val BASE_PLANETS = arrayOf(Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR, Terrain.ENDOR, Terrain.LOK, Terrain.NABOO, Terrain.RORI, Terrain.TALUS, Terrain.TATOOINE, Terrain.YAVIN4)
|
||||
}
|
||||
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.storage;
|
||||
|
||||
import com.projectswg.common.data.location.Terrain;
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.GalacticResource;
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.raw.RawResource;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public enum GalacticResourceContainer {
|
||||
INSTANCE;
|
||||
|
||||
private final Map<Long, RawResource> rawResources;
|
||||
private final Map<Long, GalacticResource> galacticResources;
|
||||
private final Map<String, GalacticResource> galacticResourcesByName;
|
||||
private final Map<RawResource, List<GalacticResource>> rawToGalactic;
|
||||
|
||||
GalacticResourceContainer() {
|
||||
this.rawResources = new ConcurrentHashMap<>();
|
||||
this.galacticResources = new ConcurrentHashMap<>();
|
||||
this.galacticResourcesByName = new ConcurrentHashMap<>();
|
||||
this.rawToGalactic = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public RawResource getRawResource(long resourceId) {
|
||||
return rawResources.get(resourceId);
|
||||
}
|
||||
|
||||
public GalacticResource getGalacticResource(long resourceId) {
|
||||
return galacticResources.get(resourceId);
|
||||
}
|
||||
|
||||
public GalacticResource getGalacticResourceByName(String resourceName) {
|
||||
return galacticResourcesByName.get(resourceName);
|
||||
}
|
||||
|
||||
public List<RawResource> getRawResources() {
|
||||
return copyImmutable(rawResources.values());
|
||||
}
|
||||
|
||||
public List<GalacticResource> getGalacticResources(RawResource rawResource) {
|
||||
return copyImmutable(rawToGalactic.get(rawResource));
|
||||
}
|
||||
|
||||
public List<GalacticResource> getSpawnedResources(Terrain terrain) {
|
||||
return galacticResources.values().stream()
|
||||
.filter(r -> !r.getSpawns(terrain).isEmpty())
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public int getSpawnedGalacticResources(RawResource rawResource) {
|
||||
return (int) galacticResources.values().stream()
|
||||
.filter(r -> !r.getSpawns().isEmpty())
|
||||
.map(r -> r.getRawResourceId() == rawResource.getId())
|
||||
.count();
|
||||
}
|
||||
|
||||
public void addRawResource(RawResource resource) {
|
||||
RawResource replaced = rawResources.put(resource.getId(), resource);
|
||||
assert replaced == null : "raw resource overwritten";
|
||||
}
|
||||
|
||||
public boolean addGalacticResource(GalacticResource resource) {
|
||||
RawResource raw = getRawResource(resource.getRawResourceId());
|
||||
Objects.requireNonNull(raw, "Invalid raw resource ID in GalacticResource!");
|
||||
if (galacticResources.putIfAbsent(resource.getId(), resource) == null) {
|
||||
if (galacticResourcesByName.putIfAbsent(resource.getName(), resource) == null) {
|
||||
rawToGalactic.computeIfAbsent(raw, k -> new ArrayList<>()).add(resource);
|
||||
return true;
|
||||
} else {
|
||||
galacticResources.remove(resource.getId());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<GalacticResource> getAllResources() {
|
||||
return copyImmutable(galacticResources.values());
|
||||
}
|
||||
|
||||
public static GalacticResourceContainer getContainer() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static <T> List<T> copyImmutable(Collection<T> list) {
|
||||
if (list == null)
|
||||
return Collections.unmodifiableList(new ArrayList<>());
|
||||
return List.copyOf(list);
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
package com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.storage
|
||||
|
||||
import com.projectswg.common.data.location.Terrain
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.GalacticResource
|
||||
import com.projectswg.holocore.resources.gameplay.crafting.resource.raw.RawResource
|
||||
import java.lang.NullPointerException
|
||||
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
object GalacticResourceContainer {
|
||||
|
||||
val rawResources: List<RawResource>
|
||||
get() = rawResourceMap.values.toList()
|
||||
|
||||
private val rawResourceMap = ConcurrentHashMap<Long, RawResource>()
|
||||
private val galacticResourceMap = ConcurrentHashMap<Long, GalacticResource>()
|
||||
private val galacticResourcesByName = ConcurrentHashMap<String, GalacticResource>()
|
||||
private val rawToGalactic = ConcurrentHashMap<RawResource, MutableList<GalacticResource>>()
|
||||
|
||||
val allResources: List<GalacticResource>
|
||||
get() = galacticResourceMap.values.toList()
|
||||
|
||||
fun getRawResource(resourceId: Long): RawResource? {
|
||||
return rawResourceMap[resourceId]
|
||||
}
|
||||
|
||||
fun getGalacticResource(resourceId: Long): GalacticResource? {
|
||||
return galacticResourceMap[resourceId]
|
||||
}
|
||||
|
||||
fun getGalacticResourceByName(resourceName: String): GalacticResource? {
|
||||
return galacticResourcesByName[resourceName]
|
||||
}
|
||||
|
||||
fun getGalacticResources(rawResource: RawResource): List<GalacticResource> {
|
||||
return rawToGalactic[rawResource]?.toList() ?: ArrayList()
|
||||
}
|
||||
|
||||
fun getSpawnedResources(terrain: Terrain): List<GalacticResource> {
|
||||
return galacticResourceMap.values.filter { r -> r.getSpawns(terrain).isNotEmpty() }
|
||||
}
|
||||
|
||||
fun getSpawnedGalacticResources(rawResource: RawResource): Int {
|
||||
return galacticResourceMap.values.count { r -> r.rawResourceId == rawResource.id && r.spawns.isNotEmpty() }
|
||||
}
|
||||
|
||||
fun addRawResource(resource: RawResource) {
|
||||
val replaced = rawResourceMap.put(resource.id, resource)
|
||||
assert(replaced == null) { "raw resource overwritten" }
|
||||
}
|
||||
|
||||
fun addGalacticResource(resource: GalacticResource): Boolean {
|
||||
val raw = getRawResource(resource.rawResourceId) ?: throw NullPointerException("Invalid raw resource ID in GalacticResource")
|
||||
if (galacticResourceMap.putIfAbsent(resource.id, resource) == null) {
|
||||
if (galacticResourcesByName.putIfAbsent(resource.name, resource) == null) {
|
||||
rawToGalactic.computeIfAbsent(raw) { ArrayList() }.add(resource)
|
||||
return true
|
||||
} else {
|
||||
galacticResourceMap.remove(resource.id)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -115,6 +115,11 @@ public class RawResource {
|
||||
return recycled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RawResource[id="+id+" name="+name+" type="+type+"]";
|
||||
}
|
||||
|
||||
public static RawResourceBuilder builder(long id) {
|
||||
return new RawResourceBuilder(id);
|
||||
}
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ class StaticItemLoader internal constructor() : DataLoader() {
|
||||
|
||||
val armorLevel: String = set.getText("armor_level")
|
||||
val armorType: ArmorType
|
||||
val protection: Double = set.getReal("protection")
|
||||
val protection: Int = set.getInt("protection").toInt()
|
||||
val requiredFaction: String = set.getText("required_faction")
|
||||
val requiredLevel: Int = set.getInt("required_level").toInt()
|
||||
val requiredProfession: String = set.getText("required_profession")
|
||||
|
||||
+5
-1
@@ -40,6 +40,7 @@ import com.projectswg.holocore.resources.support.data.server_info.CachedObjectDa
|
||||
import com.projectswg.holocore.resources.support.data.server_info.ObjectDatabase;
|
||||
import com.projectswg.holocore.resources.support.global.player.AccessLevel;
|
||||
import com.projectswg.holocore.resources.support.global.player.Player;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject;
|
||||
import com.projectswg.holocore.services.support.global.chat.ChatRoomService;
|
||||
import com.projectswg.holocore.services.support.global.zone.CharacterLookupService.PlayerLookup;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -327,7 +328,10 @@ public class ChatRoomHandler {
|
||||
ChatRoomMessage chatRoomMessage = new ChatRoomMessage(sender, room.getId(), message, oob);
|
||||
for (ChatAvatar member : room.getMembers()) {
|
||||
Player player = getPlayer(member);
|
||||
if (player.getPlayerObject().isIgnored(sender.getName()))
|
||||
if (player == null)
|
||||
continue;
|
||||
PlayerObject playerObject = player.getPlayerObject();
|
||||
if (playerObject != null && playerObject.isIgnored(sender.getName()))
|
||||
continue;
|
||||
|
||||
player.sendPacket(chatRoomMessage);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ public final class CmdRequestCoreSample implements ICmdCallback {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player player, SWGObject target, @NotNull String args) {
|
||||
GalacticResource resource = GalacticResourceContainer.getContainer().getGalacticResourceByName(args);
|
||||
GalacticResource resource = GalacticResourceContainer.INSTANCE.getGalacticResourceByName(args);
|
||||
if (resource == null) {
|
||||
SystemMessageIntent.broadcastPersonal(player, "@survey:sample_select_type");
|
||||
return;
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public final class CmdRequestSurvey implements ICmdCallback {
|
||||
if (!(target instanceof TangibleObject))
|
||||
return;
|
||||
|
||||
GalacticResource resource = GalacticResourceContainer.getContainer().getGalacticResourceByName(args);
|
||||
GalacticResource resource = GalacticResourceContainer.INSTANCE.getGalacticResourceByName(args);
|
||||
if (resource == null) {
|
||||
SystemMessageIntent.broadcastPersonal(player, "Unknown resource: " + args);
|
||||
return;
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.concurrent.ThreadLocalRandom
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.max
|
||||
import kotlin.math.sin
|
||||
|
||||
class NpcCombatMode(obj: AIObject) : NpcMode(obj) {
|
||||
|
||||
+13
-16
@@ -70,32 +70,33 @@ object StaticItemCreator {
|
||||
if (info.requiredProfession.isNotEmpty())
|
||||
obj.addAttribute("class_required", "@ui_roadmap:title_" + info.requiredProfession)
|
||||
obj.addAttribute("required_combat_level", info.requiredLevel.toString())
|
||||
|
||||
val kineticMax: Int
|
||||
val energyMax: Int
|
||||
when (info.armorType) {
|
||||
StaticItemLoader.ArmorItemInfo.ArmorType.ASSAULT -> {
|
||||
kineticMax = 7000
|
||||
energyMax = 5000
|
||||
kineticMax = info.protection + 1000
|
||||
energyMax = info.protection - 1000
|
||||
obj.addAttribute("armor_category", "@obj_attr_n:armor_assault")
|
||||
}
|
||||
StaticItemLoader.ArmorItemInfo.ArmorType.BATTLE -> {
|
||||
kineticMax = 6000
|
||||
energyMax = 6000
|
||||
kineticMax = info.protection
|
||||
energyMax = info.protection
|
||||
obj.addAttribute("armor_category", "@obj_attr_n:armor_battle")
|
||||
}
|
||||
StaticItemLoader.ArmorItemInfo.ArmorType.RECON -> {
|
||||
kineticMax = 5000
|
||||
energyMax = 7000
|
||||
kineticMax = info.protection - 1000
|
||||
energyMax = info.protection + 1000
|
||||
obj.addAttribute("armor_category", "@obj_attr_n:armor_reconnaissance")
|
||||
}
|
||||
}
|
||||
|
||||
obj.addAttribute("cat_armor_standard_protection.kinetic", calculateProtection(kineticMax, info.protection))
|
||||
obj.addAttribute("cat_armor_standard_protection.energy", calculateProtection(energyMax, info.protection))
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_heat", calculateProtection(6000, info.protection))
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_cold", calculateProtection(6000, info.protection))
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_acid", calculateProtection(6000, info.protection))
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_electricity", calculateProtection(6000, info.protection))
|
||||
obj.addAttribute("cat_armor_standard_protection.kinetic", kineticMax.toString())
|
||||
obj.addAttribute("cat_armor_standard_protection.energy", energyMax.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_heat", info.protection.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_cold", info.protection.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_acid", info.protection.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_electricity", info.protection.toString())
|
||||
|
||||
applySkillMods(obj, info.skillMods)
|
||||
applyColors(obj, info.color)
|
||||
@@ -244,8 +245,4 @@ object StaticItemCreator {
|
||||
return if (races.isEmpty()) "" else races.substring(0, races.length - 1)
|
||||
}
|
||||
|
||||
private fun calculateProtection(max: Int, protection: Double): String {
|
||||
return floor(max * protection).toInt().toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ public class SWGObjectRadial implements RadialHandlerInterface {
|
||||
// We don't use moveToContainer, because that would trigger auto-stacking.
|
||||
newStack.systemMove(container);
|
||||
|
||||
ContainerTransferIntent.broadcast(newStack, null, container);
|
||||
ContainerTransferIntent.Companion.broadcast(newStack, null, -1, container, newStack.getSlotArrangement());
|
||||
|
||||
ObjectCreatedIntent.broadcast(newStack);
|
||||
} catch (NumberFormatException e) {
|
||||
|
||||
@@ -233,17 +233,19 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
|
||||
*/
|
||||
public void moveToContainer(@Nullable SWGObject newParent) {
|
||||
SWGObject oldParent = parent;
|
||||
int oldArrangement = this.slotArrangement;
|
||||
if (systemMove(newParent))
|
||||
broadcast(new ContainerTransferIntent(this, oldParent, newParent));
|
||||
broadcast(new ContainerTransferIntent(this, oldParent, oldArrangement, newParent, this.slotArrangement));
|
||||
}
|
||||
|
||||
public void moveToSlot(@NotNull SWGObject newParent, String slot, int arrangementId) {
|
||||
SWGObject oldParent = parent;
|
||||
int oldArrangement = this.slotArrangement;
|
||||
if (oldParent != newParent) {
|
||||
if (oldParent != null)
|
||||
oldParent.removeObject(this);
|
||||
newParent.addSlottedObject(this, List.of(slot), arrangementId);
|
||||
broadcast(new ContainerTransferIntent(this, oldParent, newParent));
|
||||
broadcast(new ContainerTransferIntent(this, oldParent, oldArrangement, newParent, slotArrangement));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-12
@@ -42,6 +42,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* CREO 4
|
||||
@@ -50,6 +52,7 @@ import java.util.Set;
|
||||
class CreatureObjectClientServerNP implements Persistable, MongoPersistable {
|
||||
|
||||
private final CreatureObject obj;
|
||||
private final Lock skillModLock = new ReentrantLock();
|
||||
|
||||
/** CREO4-00 */ private float accelPercent = 1;
|
||||
/** CREO4-01 */ private float accelScale = 1;
|
||||
@@ -99,19 +102,24 @@ class CreatureObjectClientServerNP implements Persistable, MongoPersistable {
|
||||
// TODO: Add Bonus Attribute Setters
|
||||
|
||||
public void adjustSkillmod(@NotNull String skillModName, int base, int modifier) {
|
||||
SkillMod skillMod = skillMods.get(skillModName);
|
||||
|
||||
if (skillMod == null) {
|
||||
// They didn't have this SkillMod already.
|
||||
skillMods.put(skillModName, new SkillMod(base, modifier));
|
||||
} else {
|
||||
// They already had this skillmod.
|
||||
// All we need to do is adjust the base and the modifier and send an update
|
||||
skillMod.adjustBase(base);
|
||||
skillMod.adjustModifier(modifier);
|
||||
skillMods.update(skillModName);
|
||||
skillModLock.lock();
|
||||
try {
|
||||
SkillMod skillMod = skillMods.get(skillModName);
|
||||
|
||||
if (skillMod == null) {
|
||||
// They didn't have this SkillMod already.
|
||||
skillMods.put(skillModName, new SkillMod(base, modifier));
|
||||
} else {
|
||||
// They already had this skillmod.
|
||||
// All we need to do is adjust the base and the modifier and send an update
|
||||
skillMod.adjustBase(base);
|
||||
skillMod.adjustModifier(modifier);
|
||||
skillMods.update(skillModName);
|
||||
}
|
||||
skillMods.sendDeltaMessage(obj);
|
||||
} finally {
|
||||
skillModLock.unlock();
|
||||
}
|
||||
skillMods.sendDeltaMessage(obj);
|
||||
}
|
||||
|
||||
public int getSkillModValue(@NotNull String skillModName) {
|
||||
|
||||
+4
-3
@@ -149,9 +149,9 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
|
||||
DamageType damageType = getDamageType(command, weapon); // Will be based on the equipped weapon or the combat command
|
||||
int rawDamage = calculateWeaponDamage(source, weapon, command) + command.getAddedDamage();
|
||||
int finalDamage = rawDamage;
|
||||
|
||||
info.setRawDamage(rawDamage);
|
||||
info.setFinalDamage(rawDamage);
|
||||
info.setDamageType(damageType);
|
||||
|
||||
// The armor of the target will mitigate some of the damage
|
||||
@@ -162,12 +162,13 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
|
||||
// End rolls
|
||||
int targetHealth = target.getHealth();
|
||||
boolean incapacitate = targetHealth <= finalDamage;
|
||||
|
||||
if (incapacitate) {
|
||||
final int finalDamage;
|
||||
if (targetHealth <= info.getFinalDamage()) {
|
||||
finalDamage = targetHealth; // Target took more damage than they had health left. Final damage becomes the amount of remaining health.
|
||||
RequestCreatureDeathIntent.broadcast(source, target);
|
||||
} else {
|
||||
finalDamage = info.getFinalDamage();
|
||||
target.modifyHealth(-finalDamage);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class ResourceService extends Service {
|
||||
public boolean initialize() {
|
||||
container.loadResources();
|
||||
for (RawResource rawResource : container.getResources()) {
|
||||
GalacticResourceContainer.getContainer().addRawResource(rawResource);
|
||||
GalacticResourceContainer.INSTANCE.addRawResource(rawResource);
|
||||
}
|
||||
spawner.initialize();
|
||||
spawnerUpdater.startWithFixedRate(0, TimeUnit.HOURS.toMillis(3));
|
||||
|
||||
-214
@@ -1,214 +0,0 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.holocore.services.gameplay.player.experience.skills;
|
||||
|
||||
import com.projectswg.holocore.intents.gameplay.player.experience.skills.SkillModIntent;
|
||||
import com.projectswg.holocore.intents.support.objects.swg.ContainerTransferIntent;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
|
||||
import me.joshlarson.jlcommon.control.IntentHandler;
|
||||
import me.joshlarson.jlcommon.control.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Manages protection granted to the player when equipping a Jedi robe or a piece of equipment.
|
||||
* Also adds additional protection granted by innate armor.
|
||||
*/
|
||||
public class ProtectionService extends Service {
|
||||
|
||||
private final Map<String, Integer> armorSlotProtectionMap; // Note that the values of this Map add up to 100.0
|
||||
private final Map<String, Integer> robeProtectionMap;
|
||||
private static final int ARM_RPOTECTION = 7;
|
||||
|
||||
public ProtectionService() {
|
||||
armorSlotProtectionMap = Map.of( // This map is unmodifiable
|
||||
"chest2", 37,
|
||||
"pants1", 21,
|
||||
"hat", 14,
|
||||
"bracer_upper_l", ARM_RPOTECTION,
|
||||
"bracer_upper_r", ARM_RPOTECTION,
|
||||
"bicep_l", ARM_RPOTECTION,
|
||||
"bicep_r", ARM_RPOTECTION
|
||||
);
|
||||
|
||||
robeProtectionMap = Map.of( // This map is unmodifiable
|
||||
"pseudo_1", 1400, // Faint
|
||||
"pseudo_2", 3000, // Weak
|
||||
"pseudo_3", 4000, // Lucent
|
||||
"pseudo_4", 5000, // Luminous
|
||||
"pseudo_5", 6500 // Radiant
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
// Sanity check
|
||||
int armorProtectionPercentage = armorSlotProtectionMap
|
||||
.values()
|
||||
.stream()
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum();
|
||||
|
||||
return super.initialize() && armorProtectionPercentage == 100;
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private void handleContainerTransferIntent(ContainerTransferIntent intent) {
|
||||
SWGObject item = intent.getObject();
|
||||
SWGObject newContainer = intent.getContainer();
|
||||
SWGObject oldContainer = intent.getOldContainer();
|
||||
|
||||
if (newContainer == null || oldContainer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newContainer instanceof CreatureObject) {
|
||||
// They equipped something
|
||||
handleTransfer(item, (CreatureObject) newContainer, true); // newContainer is a character
|
||||
} else if (oldContainer instanceof CreatureObject) {
|
||||
// They unequipped something
|
||||
handleTransfer(item, (CreatureObject) oldContainer, false); // oldContainer is a character
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTransfer(SWGObject item, CreatureObject container, boolean equip) {
|
||||
switch (item.getGameObjectType()) {
|
||||
case GOT_CLOTHING_CLOAK:
|
||||
handleTransferRobe(item, container, equip);
|
||||
break;
|
||||
case GOT_ARMOR_HEAD:
|
||||
handleTransferArmor(item, "hat", container, equip);
|
||||
break;
|
||||
case GOT_ARMOR_BODY:
|
||||
handleTransferArmor(item, "chest2", container, equip);
|
||||
break;
|
||||
case GOT_ARMOR_LEG:
|
||||
handleTransferArmor(item, "pants1", container, equip);
|
||||
break;
|
||||
case GOT_ARMOR_ARM:
|
||||
// Covers both biceps and both bracers. They all have the same protection weight.
|
||||
handleTransferArmor(item, "bicep_r", container, equip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTransferArmor(SWGObject armor, String slotName, CreatureObject creature, boolean equip) {
|
||||
Integer slotProtection = armorSlotProtectionMap.get(slotName);
|
||||
|
||||
if (equip) {
|
||||
// They equipped this piece or armor. Check if they have a jedi robe with protection equipped. If they do, stop here.
|
||||
Collection<SWGObject> slottedObjects = creature.getSlottedObjects();
|
||||
|
||||
for (SWGObject slottedObject : slottedObjects) {
|
||||
if (slottedObject.hasAttribute("@obj_attr_n:protection_level")) {
|
||||
// Jedi robe equipped. Don't give them more protection from the piece of equipped armor.
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// They unequipped this piece of armor. Deduct the protection instead of adding it.
|
||||
slotProtection = -slotProtection;
|
||||
}
|
||||
|
||||
adjustArmorProtectionType(creature, armor, "kinetic", "cat_armor_standard_protection.kinetic", slotProtection);
|
||||
adjustArmorProtectionType(creature, armor, "energy", "cat_armor_standard_protection.energy", slotProtection);
|
||||
adjustArmorProtectionType(creature, armor, "heat", "cat_armor_special_protection.special_protection_type_heat", slotProtection);
|
||||
adjustArmorProtectionType(creature, armor, "cold", "cat_armor_special_protection.special_protection_type_cold", slotProtection);
|
||||
adjustArmorProtectionType(creature, armor, "acid", "cat_armor_special_protection.special_protection_type_acid", slotProtection);
|
||||
adjustArmorProtectionType(creature, armor, "electricity", "cat_armor_special_protection.special_protection_type_electricity", slotProtection);
|
||||
}
|
||||
|
||||
private int getWeightedProtection(SWGObject item, String attribute, Integer slotProtection) {
|
||||
if (!item.hasAttribute(attribute)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String attributeRaw = item.getAttribute(attribute);
|
||||
double protection = Double.parseDouble(attributeRaw);
|
||||
double weighted = protection * slotProtection / 100.0;
|
||||
|
||||
return (int) weighted;
|
||||
}
|
||||
|
||||
private void handleTransferRobe(SWGObject robe, CreatureObject creature, boolean equip) {
|
||||
// Deduct any existing armor protection if the robe is being equipped or add it back if the robe is unequipped
|
||||
for (String slotName : armorSlotProtectionMap.keySet()) {
|
||||
SWGObject slottedObject = creature.getSlottedObject(slotName);
|
||||
|
||||
if (slottedObject != null) {
|
||||
handleTransferArmor(slottedObject, slotName, creature, !equip);
|
||||
}
|
||||
}
|
||||
|
||||
int robeProtection = robeProtection(robe);
|
||||
|
||||
if (robeProtection == 0) {
|
||||
// Robe doesn't offer protection. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!equip) {
|
||||
// They unequipped this item. Deduct the protection instead of adding it.
|
||||
robeProtection *= -1.0;
|
||||
}
|
||||
|
||||
adjustRobeProtectionType(creature, "kinetic", robeProtection);
|
||||
adjustRobeProtectionType(creature, "energy", robeProtection);
|
||||
adjustRobeProtectionType(creature, "heat", robeProtection);
|
||||
adjustRobeProtectionType(creature, "cold", robeProtection);
|
||||
adjustRobeProtectionType(creature, "acid", robeProtection);
|
||||
adjustRobeProtectionType(creature, "electricity", robeProtection);
|
||||
}
|
||||
|
||||
private void adjustArmorProtectionType(CreatureObject creature, SWGObject armor, String skillModName, String attribute, Integer slotProtection) {
|
||||
int protection = getWeightedProtection(armor, attribute, slotProtection);
|
||||
|
||||
if (protection != 0)
|
||||
new SkillModIntent(skillModName, 0, protection, creature).broadcast();
|
||||
}
|
||||
|
||||
private void adjustRobeProtectionType(CreatureObject creature, String skillModName, int robeProtection) {
|
||||
if (robeProtection != 0)
|
||||
new SkillModIntent(skillModName, 0, robeProtection, creature).broadcast();
|
||||
}
|
||||
|
||||
private int robeProtection(SWGObject item) {
|
||||
String protectionLevel = item.getAttribute("@obj_attr_n:protection_level");
|
||||
|
||||
if (protectionLevel == null) {
|
||||
return 0; // This robe does not offer protection
|
||||
}
|
||||
|
||||
String key = protectionLevel.replace("@obj_attr_n:", "");
|
||||
|
||||
return robeProtectionMap.getOrDefault(key, 0);
|
||||
}
|
||||
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
package com.projectswg.holocore.services.gameplay.player.experience.skills
|
||||
|
||||
import com.projectswg.common.data.objects.GameObjectType
|
||||
import com.projectswg.holocore.intents.gameplay.player.experience.skills.SkillModIntent
|
||||
import com.projectswg.holocore.intents.support.objects.swg.ContainerTransferIntent
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
|
||||
import com.projectswg.holocore.resources.support.objects.swg.player.Profession
|
||||
import me.joshlarson.jlcommon.control.IntentHandler
|
||||
import me.joshlarson.jlcommon.control.Service
|
||||
|
||||
/**
|
||||
* Manages protection granted to the player when equipping a Jedi robe or a piece of equipment.
|
||||
* Also adds additional protection granted by innate armor.
|
||||
*/
|
||||
class ProtectionService : Service() {
|
||||
|
||||
private val attributeLookup = mapOf( // Unmodifiable
|
||||
"kinetic" to "cat_armor_standard_protection.kinetic",
|
||||
"energy" to "cat_armor_standard_protection.energy",
|
||||
"heat" to "cat_armor_special_protection.special_protection_type_heat",
|
||||
"cold" to "cat_armor_special_protection.special_protection_type_cold",
|
||||
"acid" to "cat_armor_special_protection.special_protection_type_acid",
|
||||
"electricity" to "cat_armor_special_protection.special_protection_type_electricity"
|
||||
)
|
||||
private val armorSlotProtectionMap = mapOf( // Unmodifiable
|
||||
"chest2" to 37,
|
||||
"pants1" to 21,
|
||||
"hat" to 14,
|
||||
"bracer_upper_l" to ARM_RPOTECTION,
|
||||
"bracer_upper_r" to ARM_RPOTECTION,
|
||||
"bicep_l" to ARM_RPOTECTION,
|
||||
"bicep_r" to ARM_RPOTECTION
|
||||
)
|
||||
|
||||
init {
|
||||
assert(armorSlotProtectionMap.values.sum() == 100)
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private fun handleContainerTransferIntent(intent: ContainerTransferIntent) {
|
||||
val item = intent.obj
|
||||
val newContainer = intent.container
|
||||
val oldContainer = intent.oldContainer
|
||||
|
||||
if (newContainer is CreatureObject) {
|
||||
// They equipped something
|
||||
handleTransfer(item, newContainer, item.arrangement.getOrNull(intent.arrangement-4) ?: EMPTY_LIST, true) // newContainer is a character
|
||||
} else if (oldContainer is CreatureObject) {
|
||||
// They unequipped something
|
||||
handleTransfer(item, oldContainer, item.arrangement.getOrNull(intent.oldArrangement-4) ?: EMPTY_LIST, false) // oldContainer is a character
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleTransfer(item: SWGObject, creature: CreatureObject, arrangement: List<String>, equip: Boolean) {
|
||||
val jedi = creature.playerObject?.profession == Profession.FORCE_SENSITIVE
|
||||
val robe = item.gameObjectType == GameObjectType.GOT_CLOTHING_CLOAK
|
||||
|
||||
if (jedi && robe) {
|
||||
updateProtection(creature, equip) { attribute -> item.calculateProtection(attribute) }
|
||||
} else if (!jedi && !robe) {
|
||||
updateProtection(creature, equip) { attribute -> arrangement.sumBy { slot -> item.calculateProtection(attribute, armorSlotProtectionMap[slot] ?: 0) } }
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun updateProtection(creature: CreatureObject, equip: Boolean, calculateProtection: (attribute: String) -> Int) {
|
||||
for ((skillModName, attribute) in attributeLookup) {
|
||||
val protection = calculateProtection(attribute)
|
||||
SkillModIntent(skillModName, 0, if (equip) protection else -protection, creature).broadcast()
|
||||
}
|
||||
}
|
||||
|
||||
private fun SWGObject.calculateProtection(attribute: String) = (getAttribute(attribute)?.toIntOrNull() ?: 0)
|
||||
private fun SWGObject.calculateProtection(attribute: String, slotProtection: Int) = (getAttribute(attribute)?.toIntOrNull() ?: 0) * slotProtection / 100
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ARM_RPOTECTION = 7
|
||||
|
||||
private val EMPTY_LIST = listOf<String>()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package com.projectswg.holocore.services.support.npc.ai;
|
||||
|
||||
import com.projectswg.common.data.location.Location;
|
||||
import com.projectswg.holocore.intents.gameplay.combat.CreatureKilledIntent;
|
||||
import com.projectswg.holocore.intents.support.npc.ai.CompileNpcMovementIntent;
|
||||
import com.projectswg.holocore.intents.support.npc.ai.StartNpcMovementIntent;
|
||||
import com.projectswg.holocore.intents.support.npc.ai.StopNpcMovementIntent;
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationOffset;
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationPoint;
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationRouteType;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject;
|
||||
import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool;
|
||||
import me.joshlarson.jlcommon.control.IntentHandler;
|
||||
import me.joshlarson.jlcommon.control.Service;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class AIMovementService extends Service {
|
||||
|
||||
private final Map<AIObject, NavigationRoute> routes;
|
||||
private final ScheduledThreadPool movementThreads;
|
||||
|
||||
public AIMovementService() {
|
||||
this.routes = new ConcurrentHashMap<>();
|
||||
this.movementThreads = new ScheduledThreadPool(Runtime.getRuntime().availableProcessors(), "ai-movement-service-%d");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
movementThreads.start();
|
||||
movementThreads.executeWithFixedRate(1000, 1000, this::executeRoutes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
movementThreads.stop();
|
||||
return movementThreads.awaitTermination(1000);
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private void handleStartNpcMovementIntent(StartNpcMovementIntent snmi) {
|
||||
AIObject obj = snmi.getObject();
|
||||
|
||||
List<NavigationPoint> route = NavigationPoint.from(obj.getParent(), obj.getLocation(), snmi.getParent(), snmi.getDestination(), snmi.getSpeed());
|
||||
if (route.isEmpty())
|
||||
routes.remove(obj);
|
||||
else
|
||||
routes.put(obj, new NavigationRoute(obj, route, NavigationRouteType.TERMINATE));
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private void handleCompileNpcMovementIntent(CompileNpcMovementIntent snmi) {
|
||||
AIObject obj = snmi.getObject();
|
||||
List<NavigationPoint> route = new ArrayList<>(snmi.getPoints().size());
|
||||
for (NavigationPoint point : snmi.getPoints()) {
|
||||
appendRoutePoint(route, offsetLocation(point, snmi.getOffset()), snmi.getSpeed());
|
||||
}
|
||||
|
||||
if (route.isEmpty())
|
||||
routes.remove(obj);
|
||||
else
|
||||
routes.put(obj, new NavigationRoute(obj, route, snmi.getType()));
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private void handleStopNpcMovementIntent(StopNpcMovementIntent snmi) {
|
||||
routes.remove(snmi.getObject());
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private void handleCreatureKilledIntent(CreatureKilledIntent cki) {
|
||||
CreatureObject corpse = cki.getCorpse();
|
||||
if (corpse instanceof AIObject)
|
||||
routes.remove(corpse);
|
||||
}
|
||||
|
||||
private void executeRoutes() {
|
||||
routes.values().forEach(NavigationRoute::execute);
|
||||
}
|
||||
|
||||
private void appendRoutePoint(List<NavigationPoint> waypoints, NavigationPoint waypoint, double speed) {
|
||||
NavigationPoint prev = waypoints.isEmpty() ? null : waypoints.get(waypoints.size()-1);
|
||||
if (waypoint.isNoOperation()) {
|
||||
waypoints.add(waypoint);
|
||||
return;
|
||||
}
|
||||
if (prev == null) {
|
||||
waypoints.add(NavigationPoint.at(waypoint.getParent(), waypoint.getLocation(), speed));
|
||||
} else {
|
||||
if (prev.getLocation().equals(waypoint.getLocation()) && prev.getParent() == waypoint.getParent())
|
||||
return;
|
||||
waypoints.addAll(NavigationPoint.from(prev.getParent(), prev.getLocation(), waypoint.getParent(), waypoint.getLocation(), speed));
|
||||
}
|
||||
}
|
||||
|
||||
static NavigationPoint offsetLocation(NavigationPoint point, @Nullable NavigationOffset offset) {
|
||||
if (offset == null)
|
||||
return point;
|
||||
return NavigationPoint.at(point.getParent(), offsetLocation(point.getLocation(), offset), point.getSpeed());
|
||||
}
|
||||
|
||||
static Location offsetLocation(Location location, @NotNull NavigationOffset offset) {
|
||||
double oX = offset.getX();
|
||||
double oZ = offset.getZ();
|
||||
double heading = location.getYaw(); // Should be 0 - 360, with 0 representing north and 270 representing east
|
||||
double angle = Math.toRadians(heading <= 180 ? heading : (heading - 360)) + Math.atan2(oZ, oX);
|
||||
double distance = Math.sqrt(oZ*oZ + oX*oX);
|
||||
return Location.builder(location).setX(location.getX() + Math.sin(angle) * distance).setZ(location.getZ() + Math.cos(angle) * distance).build();
|
||||
}
|
||||
|
||||
private static class NavigationRoute {
|
||||
|
||||
private final AIObject obj;
|
||||
private final List<NavigationPoint> route;
|
||||
private final NavigationRouteType type;
|
||||
private final AtomicInteger index;
|
||||
|
||||
public NavigationRoute(AIObject obj, List<NavigationPoint> route, NavigationRouteType type) {
|
||||
this.obj = obj;
|
||||
this.route = route;
|
||||
this.type = type;
|
||||
this.index = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
int index = this.index.getAndIncrement();
|
||||
if (index >= route.size()) {
|
||||
switch (type) {
|
||||
case LOOP:
|
||||
this.index.set(0);
|
||||
index = 0;
|
||||
break;
|
||||
case TERMINATE:
|
||||
StopNpcMovementIntent.broadcast(obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert index < route.size() && index >= 0;
|
||||
|
||||
route.get(index).move(obj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.projectswg.holocore.services.support.npc.ai
|
||||
|
||||
import com.projectswg.common.data.location.Location
|
||||
import com.projectswg.holocore.intents.gameplay.combat.CreatureKilledIntent
|
||||
import com.projectswg.holocore.intents.support.npc.ai.CompileNpcMovementIntent
|
||||
import com.projectswg.holocore.intents.support.npc.ai.StartNpcMovementIntent
|
||||
import com.projectswg.holocore.intents.support.npc.ai.StopNpcMovementIntent
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationOffset
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationPoint
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationRouteType
|
||||
import com.projectswg.holocore.resources.support.objects.swg.custom.AIObject
|
||||
import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool
|
||||
import me.joshlarson.jlcommon.control.IntentHandler
|
||||
import me.joshlarson.jlcommon.control.Service
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class AIMovementService : Service() {
|
||||
|
||||
private val routes = ConcurrentHashMap<AIObject, NavigationRoute>()
|
||||
private val movementThreads = ScheduledThreadPool(Runtime.getRuntime().availableProcessors(), "ai-movement-service-%d")
|
||||
|
||||
override fun start(): Boolean {
|
||||
movementThreads.start()
|
||||
movementThreads.executeWithFixedRate(1000, 1000) { this.executeRoutes() }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun stop(): Boolean {
|
||||
movementThreads.stop()
|
||||
return movementThreads.awaitTermination(1000)
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private fun handleStartNpcMovementIntent(snmi: StartNpcMovementIntent) {
|
||||
val obj = snmi.getObject()
|
||||
|
||||
val route = NavigationPoint.from(obj.parent, obj.location, snmi.parent, snmi.destination, snmi.speed)
|
||||
if (route.isEmpty())
|
||||
routes.remove(obj)
|
||||
else
|
||||
routes[obj] = NavigationRoute(obj, route, NavigationRouteType.TERMINATE)
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private fun handleCompileNpcMovementIntent(snmi: CompileNpcMovementIntent) {
|
||||
val obj = snmi.getObject()
|
||||
val route = ArrayList<NavigationPoint>(snmi.points.size)
|
||||
val waypoints = snmi.points
|
||||
for ((index, point) in waypoints.withIndex()) {
|
||||
val next = waypoints.getOrNull(index+1) ?: waypoints.getOrNull(0)
|
||||
appendRoutePoint(route, offsetLocation(point, if (next == null) 0.0 else point.location.getHeadingTo(next.location), snmi.offset), snmi.speed)
|
||||
}
|
||||
|
||||
if (route.isEmpty())
|
||||
routes.remove(obj)
|
||||
else
|
||||
routes[obj] = NavigationRoute(obj, route, snmi.type)
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private fun handleStopNpcMovementIntent(snmi: StopNpcMovementIntent) {
|
||||
routes.remove(snmi.getObject())
|
||||
}
|
||||
|
||||
@IntentHandler
|
||||
private fun handleCreatureKilledIntent(cki: CreatureKilledIntent) {
|
||||
val corpse = cki.corpse
|
||||
if (corpse is AIObject)
|
||||
routes.remove(corpse)
|
||||
}
|
||||
|
||||
private fun executeRoutes() {
|
||||
routes.values.forEach { it.execute() }
|
||||
}
|
||||
|
||||
private fun appendRoutePoint(waypoints: MutableList<NavigationPoint>, waypoint: NavigationPoint, speed: Double) {
|
||||
val prev = if (waypoints.isEmpty()) null else waypoints[waypoints.size - 1]
|
||||
if (waypoint.isNoOperation) {
|
||||
waypoints.add(waypoint)
|
||||
return
|
||||
}
|
||||
if (prev == null) {
|
||||
waypoints.add(NavigationPoint.at(waypoint.parent, waypoint.location, speed))
|
||||
} else {
|
||||
if (prev.location.equals(waypoint.location) && prev.parent === waypoint.parent)
|
||||
return
|
||||
waypoints.addAll(NavigationPoint.from(prev.parent, prev.location, waypoint.parent, waypoint.location, speed))
|
||||
}
|
||||
}
|
||||
|
||||
private class NavigationRoute(private val obj: AIObject, private val route: List<NavigationPoint>, private val type: NavigationRouteType) {
|
||||
|
||||
private val index = AtomicInteger(0)
|
||||
|
||||
fun execute() {
|
||||
var index = this.index.getAndIncrement()
|
||||
if (index >= route.size) {
|
||||
when (type) {
|
||||
NavigationRouteType.LOOP -> {
|
||||
this.index.set(0)
|
||||
index = 0
|
||||
}
|
||||
NavigationRouteType.TERMINATE -> {
|
||||
StopNpcMovementIntent.broadcast(obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(index < route.size && index >= 0)
|
||||
|
||||
route[index].move(obj)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun offsetLocation(point: NavigationPoint, heading: Double, offset: NavigationOffset?): NavigationPoint {
|
||||
return if (offset == null) point else NavigationPoint.at(point.parent, offsetLocation(point.location, heading, offset), point.speed)
|
||||
}
|
||||
|
||||
internal fun offsetLocation(location: Location, heading: Double, offset: NavigationOffset): Location {
|
||||
val oX = offset.x
|
||||
val oZ = offset.z
|
||||
val cos = cos(Math.toRadians(heading)) // heading should be 0 - 360, with 0 representing north and 270 representing east
|
||||
val sin = sin(Math.toRadians(heading))
|
||||
val nX = oX * cos - oZ * sin
|
||||
val nZ = oZ * cos + oX * sin
|
||||
return Location.builder(location).setX(location.x + nX).setZ(location.z + nZ).build()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,9 +45,9 @@ public class TestLocation extends TestRunnerNoIntents {
|
||||
|
||||
assertEquals(0, origin.getHeadingTo(pointNorth), 1E-7);
|
||||
assertEquals(0, pointSouth.getHeadingTo(pointNorth), 1E-7);
|
||||
assertEquals(90, origin.getHeadingTo(pointEast), 1E-7);
|
||||
assertEquals(270, origin.getHeadingTo(pointEast), 1E-7);
|
||||
assertEquals(180, origin.getHeadingTo(pointSouth), 1E-7);
|
||||
assertEquals(270, origin.getHeadingTo(pointWest), 1E-7);
|
||||
assertEquals(90, origin.getHeadingTo(pointWest), 1E-7);
|
||||
|
||||
assertEquals(0, Location.builder(origin).setHeading(0).build().getYaw(), 1E-7);
|
||||
assertEquals(90, Location.builder(origin).setHeading(90).build().getYaw(), 1E-7);
|
||||
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***********************************************************************************/
|
||||
|
||||
package com.projectswg.holocore.services.gameplay.player.experience
|
||||
|
||||
import com.projectswg.holocore.resources.support.objects.ObjectCreator
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
|
||||
import com.projectswg.holocore.resources.support.objects.swg.player.Profession
|
||||
import com.projectswg.holocore.services.gameplay.player.experience.skills.ProtectionService
|
||||
import com.projectswg.holocore.services.gameplay.player.experience.skills.skillmod.SkillModService
|
||||
import com.projectswg.holocore.test.resources.GenericCreatureObject
|
||||
import com.projectswg.holocore.test.runners.TestRunnerSynchronousIntents
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class TestProtectionService: TestRunnerSynchronousIntents() {
|
||||
|
||||
@Before
|
||||
fun setupServices() {
|
||||
registerService(ProtectionService())
|
||||
registerService(SkillModService())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJediRobeEquip() {
|
||||
val jedi = createCreature(1, Profession.FORCE_SENSITIVE)
|
||||
val notjedi = createCreature(2, Profession.SMUGGLER)
|
||||
val armor = ProtectionArmor()
|
||||
|
||||
// Nothing equipped yet
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Jedi gets protection from robe
|
||||
armor.simpleRobe.moveToContainer(jedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Should remove the protection
|
||||
armor.simpleRobe.moveToContainer(null)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Non-jedi shouldn't get protection
|
||||
armor.simpleRobe.moveToContainer(notjedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Nope, not even really nice protection
|
||||
armor.betterRobe.moveToContainer(notjedi)
|
||||
Assert.assertNotEquals("simple robe should have moved away", armor.simpleRobe.parent, notjedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Resetting - no change expected
|
||||
armor.simpleRobe.moveToContainer(null)
|
||||
armor.betterRobe.moveToContainer(null)
|
||||
Assert.assertNull("simple robe should have moved away", armor.simpleRobe.parent)
|
||||
Assert.assertNull("better robe should have moved away", armor.simpleRobe.parent)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Jedi gets protection from robe (same as earlier)
|
||||
armor.simpleRobe.moveToContainer(jedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Jedi gets nice protection
|
||||
armor.betterRobe.moveToContainer(jedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 7000, energy = 7000, heat = 7000, cold = 7000, acid = 7000, electricity = 7000)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// All good things must come to an end eventually
|
||||
armor.simpleRobe.moveToContainer(null)
|
||||
armor.betterRobe.moveToContainer(null)
|
||||
Assert.assertNull("simple robe should have moved away", armor.simpleRobe.parent)
|
||||
Assert.assertNull("better robe should have moved away", armor.simpleRobe.parent)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRISEquip() {
|
||||
val jedi = createCreature(1, Profession.FORCE_SENSITIVE)
|
||||
val notjedi = createCreature(2, Profession.SMUGGLER)
|
||||
val armor = ProtectionArmor()
|
||||
|
||||
// Nothing equipped yet
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Jedi does not get protection from RIS
|
||||
armor.risArmor.forEach { it.moveToContainer(jedi) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Still no protection
|
||||
armor.risArmor.forEach { it.moveToContainer(null) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Non-jedi get protection from armor
|
||||
armor.risArmor.forEach { it.moveToContainer(notjedi) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi)
|
||||
|
||||
// Resetting
|
||||
armor.simpleRobe.moveToContainer(null)
|
||||
armor.betterRobe.moveToContainer(null)
|
||||
armor.risArmor.forEach { it.moveToContainer(null) }
|
||||
Assert.assertNull("simple robe should have moved away", armor.simpleRobe.parent)
|
||||
Assert.assertNull("better robe should have moved away", armor.simpleRobe.parent)
|
||||
armor.risArmor.forEach { Assert.assertNull("RIS armor should have moved away", it.parent) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// Non-jedi don't get protection from robes
|
||||
armor.simpleRobe.moveToContainer(notjedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
|
||||
// But they do from armor
|
||||
armor.risArmor.forEach { it.moveToContainer(notjedi) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi)
|
||||
|
||||
// The robe should remove everything but the helmet
|
||||
armor.simpleRobe.moveToContainer(notjedi)
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 6000*14/100, energy = 6000*14/100, heat = 6000*14/100, cold = 6000*14/100, acid = 6000*14/100, electricity = 6000*14/100)
|
||||
|
||||
// All good things must come to an end eventually
|
||||
armor.simpleRobe.moveToContainer(null)
|
||||
armor.betterRobe.moveToContainer(null)
|
||||
armor.risArmor.forEach { it.moveToContainer(null) }
|
||||
Assert.assertNull("simple robe should have moved away", armor.simpleRobe.parent)
|
||||
Assert.assertNull("better robe should have moved away", armor.simpleRobe.parent)
|
||||
armor.risArmor.forEach { Assert.assertNull("RIS armor should have moved away", it.parent) }
|
||||
waitForIntents()
|
||||
assertProtection(jedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
assertProtection(notjedi, kinetic = 0, energy = 0, heat = 0, cold = 0, acid = 0, electricity = 0)
|
||||
}
|
||||
|
||||
private fun assertProtection(creature: CreatureObject, kinetic: Int = 6000, energy: Int = 6000, heat: Int = 6000, cold: Int = 6000, acid: Int = 6000, electricity: Int = 6000) {
|
||||
Assert.assertEquals("kinetic", kinetic, creature.getSkillModValue("kinetic"))
|
||||
Assert.assertEquals("energy", kinetic, creature.getSkillModValue("energy"))
|
||||
Assert.assertEquals("heat", kinetic, creature.getSkillModValue("heat"))
|
||||
Assert.assertEquals("cold", kinetic, creature.getSkillModValue("cold"))
|
||||
Assert.assertEquals("acid", kinetic, creature.getSkillModValue("acid"))
|
||||
Assert.assertEquals("electricity", kinetic, creature.getSkillModValue("electricity"))
|
||||
}
|
||||
|
||||
data class ProtectionArmor(val simpleRobe: SWGObject = createSimpleRobe(), val betterRobe: SWGObject = createBetterRobe(), val risArmor: List<SWGObject> = createArmorSetRIS())
|
||||
|
||||
companion object {
|
||||
|
||||
private fun createCreature(id: Long, profession: Profession): GenericCreatureObject {
|
||||
val creature = GenericCreatureObject(id)
|
||||
creature.playerObject.profession = profession
|
||||
return creature;
|
||||
}
|
||||
|
||||
private fun createSimpleRobe() = createProtectedItem("object/tangible/wearables/robe/robe_jedi_light_s01.iff")
|
||||
private fun createBetterRobe() = createProtectedItem("object/tangible/wearables/robe/robe_jedi_dark_s01.iff", kinetic = 7000, energy = 7000, heat = 7000, cold = 7000, acid = 7000, electricity = 7000)
|
||||
|
||||
private fun createArmorSetRIS(): List<SWGObject> {
|
||||
return listOf(
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_boots.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_leggings.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_chest_plate.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_helmet.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_bicep_l.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_bicep_r.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_bracer_l.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_bracer_r.iff"),
|
||||
createProtectedItem("object/tangible/wearables/armor/ris/armor_ris_gloves.iff")
|
||||
)
|
||||
}
|
||||
|
||||
private fun createProtectedItem(template: String, kinetic: Int = 6000, energy: Int = 6000, heat: Int = 6000, cold: Int = 6000, acid: Int = 6000, electricity: Int = 6000): SWGObject {
|
||||
val obj = ObjectCreator.createObjectFromTemplate(template)
|
||||
obj.addAttribute("cat_armor_standard_protection.kinetic", kinetic.toString())
|
||||
obj.addAttribute("cat_armor_standard_protection.energy", energy.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_heat", heat.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_cold", cold.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_acid", acid.toString())
|
||||
obj.addAttribute("cat_armor_special_protection.special_protection_type_electricity", electricity.toString())
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+24
-8
@@ -29,21 +29,37 @@ package com.projectswg.holocore.services.support.npc.ai
|
||||
|
||||
import com.projectswg.common.data.location.Location
|
||||
import com.projectswg.holocore.resources.support.npc.ai.NavigationOffset
|
||||
import com.projectswg.holocore.test.runners.TestRunnerNoIntents
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class TestAIMovementService {
|
||||
class TestAIMovementService: TestRunnerNoIntents() {
|
||||
|
||||
@Test
|
||||
fun testOffsetLocation() {
|
||||
testOffset( 1.0, 1.0, 0.0, 1.0, 1.0)
|
||||
testOffset(-1.0, 1.0, 90.0, 1.0, 1.0)
|
||||
testOffset(-1.0, -1.0, 180.0, 1.0, 1.0)
|
||||
testOffset( 1.0, -1.0, 270.0, 1.0, 1.0)
|
||||
Assert.assertEquals("NORTH", 0.0, headingTo(0.0, 1.0), 1E-7)
|
||||
Assert.assertEquals("EAST", 270.0, headingTo(1.0, 0.0), 1E-7)
|
||||
Assert.assertEquals("SOUTH", 180.0, headingTo(0.0, -1.0), 1E-7)
|
||||
Assert.assertEquals("WEST", 90.0, headingTo(-1.0, 0.0), 1E-7)
|
||||
|
||||
testOffset(headingTo(0.0, 1.0), 1.0, 1.0)
|
||||
testOffset(headingTo(-1.0, 0.0), -1.0, 1.0)
|
||||
testOffset(headingTo(0.0, -1.0), -1.0, -1.0)
|
||||
testOffset(headingTo(1.0, 0.0), 1.0, -1.0)
|
||||
|
||||
testOffset(headingTo(1.0, 1.0), sqrt(2.0), 0.0)
|
||||
}
|
||||
|
||||
private fun testOffset(x: Double, z: Double, heading: Double, tx: Double, tz: Double) {
|
||||
val startLocation = Location.builder().setPosition(0.0, 0.0, 0.0).setHeading(heading).build()
|
||||
AIMovementService.offsetLocation(startLocation, NavigationOffset(tx, tz))
|
||||
private fun headingTo(eX: Double, eZ: Double): Double {
|
||||
return Location.builder().setPosition(0.0, 0.0, 0.0).build().getHeadingTo(Location.builder().setPosition(eX, 0.0, eZ).build())
|
||||
}
|
||||
|
||||
private fun testOffset(heading: Double, tx: Double, tz: Double) {
|
||||
val startLocation = Location.builder().setPosition(0.0, 0.0, 0.0).build()
|
||||
val endLocation = AIMovementService.offsetLocation(startLocation, heading, NavigationOffset(1.0, 1.0))
|
||||
Assert.assertEquals("X", tx, endLocation.x, 1E-7)
|
||||
Assert.assertEquals("Z", tz, endLocation.z, 1E-7)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-1
@@ -80,8 +80,16 @@ public abstract class TestRunnerSynchronousIntents extends TestRunner {
|
||||
boolean uninterrupted = Delay.sleepMicro(10);
|
||||
assert uninterrupted;
|
||||
}
|
||||
waitForIntents();
|
||||
}
|
||||
|
||||
protected final void waitForIntents() {
|
||||
while (intentManager.getIntentCount() > 0) {
|
||||
boolean uninterrupted = Delay.sleepMicro(10);
|
||||
boolean uninterrupted = Delay.sleepMilli(1);
|
||||
assert uninterrupted;
|
||||
}
|
||||
while (intentManager.getIntentCount() > 0) {
|
||||
boolean uninterrupted = Delay.sleepMilli(10);
|
||||
assert uninterrupted;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/***********************************************************************************
|
||||
* Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
|
||||
* *
|
||||
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
|
||||
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
|
||||
* Our goal is to create an emulator which will provide a server for players to *
|
||||
* continue playing a game similar to the one they used to play. We are basing *
|
||||
* it on the final publish of the game prior to end-game events. *
|
||||
* *
|
||||
* This file is part of Holocore. *
|
||||
* *
|
||||
* --------------------------------------------------------------------------------*
|
||||
* *
|
||||
* Holocore 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. *
|
||||
* *
|
||||
* Holocore 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 Holocore. If not, see <http:></http:>//www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
package com.projectswg.utility.clientdata
|
||||
|
||||
import com.projectswg.common.data.swgiff.parsers.SWGParser
|
||||
import com.projectswg.common.data.swgiff.parsers.terrain.TerrainDataParser
|
||||
import com.projectswg.holocore.utilities.SdbGenerator
|
||||
import me.joshlarson.jlcommon.log.Log
|
||||
import me.joshlarson.jlcommon.log.log_wrapper.ConsoleLogWrapper
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
internal class ConvertTerrain : Converter {
|
||||
|
||||
override fun convert() {
|
||||
println("Converting terrains...")
|
||||
Log.addWrapper(ConsoleLogWrapper())
|
||||
try {
|
||||
SdbGenerator(File("serverdata/terrain/terrains.sdb")).use { sdb ->
|
||||
sdb.writeColumnNames("slotName", "global", "modifiable", "observeWithParent", "exposeToWorld")
|
||||
convertFile(sdb, File("clientdata/terrain/tatooine.trn"))
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun convertFile(sdb: SdbGenerator, file: File) {
|
||||
val clientdata = SWGParser.parse(file) as TerrainDataParser
|
||||
Objects.requireNonNull(clientdata, "Failed to load clientdata")
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public enum Converters {
|
||||
ABSTRACT_SLOT_DEFINITION (ConvertSlotDefinition::new),
|
||||
ABSTRACT_SLOT_DESCRIPTORS (ConvertSlotDescriptor::new),
|
||||
ABSTRACT_SLOT_ARRANGEMENT (ConvertSlotArrangement::new),
|
||||
TERRAINS (ConvertTerrain::new),
|
||||
PROFESSION_TEMPLATES (ConvertProfessionTemplates::new);
|
||||
|
||||
private final Supplier<Converter> converter;
|
||||
|
||||
Reference in New Issue
Block a user