diff --git a/accesslevels/cs.txt b/accesslevels/cs.txt new file mode 100644 index 00000000..199f3ca9 --- /dev/null +++ b/accesslevels/cs.txt @@ -0,0 +1,71 @@ +activateinstance +activatequest +broadcast +broadcastarea +broadcastplanet +broadcastgalaxy +clearcompletedquest +clearveteranreward +createstaticitem +credits +csdumptarget +deactivtequest +destroy +editappearance +editbank +editbankaccount +editstats +findobject +findobjectbytemplate +findplayer +findcreatre +gmforcecommand +freezeplayer +unfreezeplayer +squelch +unsquelch +getgametime +getplayerid +getrank +goto +grantbadge +getveteranrewardtimecs +grantskill +granttitle +harmful +harmless +hasveteranreward +kill +killplayer +listactivequests +revokebadge +revokeskill +searchcorpse +setgrievousauthorized +setinstanceauthorized +setfirstname +setlastname +setname +setowner +gmrevive +setplayerappearance +setplayerstate +setrank +setspeed +settef +setveteranreward +showfactioninformation +snoop +uncityban +unsnoop +wipeitems +csstorytellerdestroynpcs +csstorytellerdestroyprops +csstorytellerdestroyparticles +csstorytellerdestroyallobjects +revertplayerappearance +gmclearquest +gmgrantquest +getaccountinfo +object +giveitem \ No newline at end of file diff --git a/accesslevels/dev.txt b/accesslevels/dev.txt new file mode 100644 index 00000000..81e410a1 --- /dev/null +++ b/accesslevels/dev.txt @@ -0,0 +1,95 @@ +teleport +teleportto +teleporttarget +invulnerable +setspeed +database +destroy +dumptargetinfo +dumpzoneinfo +forcecommand +giveitem +kill +killplayer +setappearance +setexperience +activateinstance +activatequest +aiignore +clearcompletedquest +clearstaticitem +credits +csdumptarget +editappearance +editbank +editbankaccount +editstats +emptymailtarget +findobject +findobjetbytemplate +findplayer +findcreature +generatecrafteditem +getgametime +getplayerid +getstationname +gmforcecommand +grantskill +granttitle +harmfull +harmless +goto +gmweapon +gmshowquest +gmregrantquest +gmveteranrewardtimecs +listactivequests +gmrevive +maxforcepower +overrideactivemonths +overridepadawantrialseligibility +qatool +resetjedi +revokebadge +revokeskill +searchcorpse +setfaction +setfactionstanding +setname +setplayerstate +setrank +setgrievousauthorized +sethue +setinstanceauthorized +setfirstname +setlastname +setplayerappearance +setplayerstate +settef +setveteranreward +showfactioninformation +snoop +wipeitems +csstorytellerdestroynpcs +csstorytellerdestroyprops +csstorytellerdestroyparticles +csstorytellerdestroyallobjects +revertplayerappearance +eventshuttledrop +eventstartraid +gmclearquest +gmgrantquest +gmspawnship +initializecomponent +combatdatarecord +combatdataclear +combatdatareport +combatdatastop +combatmodecheck +startrestussstagetwo +completerestussstageone +spewcommandqueue +object +giveitem +createcreature +createspawningelement \ No newline at end of file diff --git a/accesslevels/ec.txt b/accesslevels/ec.txt new file mode 100644 index 00000000..5f159247 --- /dev/null +++ b/accesslevels/ec.txt @@ -0,0 +1,58 @@ +teleport +teleportto +teleporttarget +invulnerable +setspeed +gmforcecommand +grantbadge +grantskill +granttitle +revokebadge +revokeskill +revoketitle +kill +killplayer +gmrevive +revokeappearance +setfaction +setfactionstanding +setrank +setfirstname +setlastname +setgodmode +sethue +setplayerappearnace +setplayerstate +settef +revertplayerappearance +freezeplayer +unfreezeplayer +squelch +unsquelch +createcreature +createspawningelement +createstaticitem +editappearance +broadcast +broadcastarea +broadcastplanet +broadcastgalaxy +eventbuff +eventbuffarea +eventbufftarget +eventclearstates +eventdamage +eventmovetome +eventstorepet +eventtefarea +eventtefclear +eventteftarget +eventundomovetome +eventvaderchoke +eventweapon +getplayerid +giveitem +eventshuttledrop +eventstartraid +startrestussstagetwo +completerestussstageone \ No newline at end of file diff --git a/accesslevels/lead.txt b/accesslevels/lead.txt new file mode 100644 index 00000000..339fc644 --- /dev/null +++ b/accesslevels/lead.txt @@ -0,0 +1,128 @@ +activateinstance +activatequest +aiignore +broadcast +broadcastarea +broadcastgalaxy +broadcastplanet +clearcompletedquest +clearveteranreward +createstaticitem +credits +csdumptarget +deactivatequest +destroy +editappearance +editbank +editbankaccount +editstats +emptymailtarget +eventbuff +eventbuffarea +eventbufftarget +eventclearstates +eventdamage +eventmovetome +eventstorepet +eventtefarea +eventtefclear +eventteftarget +eventundomovetome +eventvaderchoke +eventweapon +findobject +findobjectbytemplate +findplayer +findcreature +forcecommand +freezeplayer +generatecrafteditem +squelch +unsquelch +getgametime +getplayerid +getrank +getstationname +getveteranrewardtimecs +gmforcecommand +gmforcerank +gmfsvillage +gmregrantquest +gmshowquest +gmweapon +goto +grantbadge +grantbadgearea +grantpadawantrialseligibility +grantskill +granttitle +harmful +harmless +hasveteranreward +invulnerable +kill +listactivequests +listcompletedquests +maxforcepower +overrideactivemonths +overridepadawantrialseligibility +qatool +resetjedi +revokebadge +revokeskill +searchcorpse +setbiographyadmin +setfaction +setfactionstanding +setfirstname +setgrievousauthorized +setgodmode +sethue +setinstanceauthorized +gmrevive +setlastname +setname +setowner +setplayerappearance +setplayerstate +setrank +setspeed +settef +setveteranreward +showfactioninformation +snoop +uncityban +unfreezeplayer +unsnoop +wipeitems +csstorytellerdestroynpcs +csstorytellerdestroyprops +csstorytellerdestroyparticles +csstorytellerdestroyallobjects +revertplayerappearance +eventshuttledrop +eventstartraid +gmclearquest +gmgrantquest +gmspawnship +initializecomponent +killplayer +setloginmessage +setwardenloginmessage +combatdatarecord +combatdataclear +combatdatareport +combatdatastop +combatmodecheck +findwarden +grantwarden +revokewarden +startrestussstagetwo +completerestussstageone +spewcommandqueue +server +getaccountinfo +object +giveitem +createcreature +createspawningelement \ No newline at end of file diff --git a/accesslevels/qa.txt b/accesslevels/qa.txt new file mode 100644 index 00000000..ff168a9d --- /dev/null +++ b/accesslevels/qa.txt @@ -0,0 +1,62 @@ +teleport +teleportto +teleporttarget +invulnerable +setspeed +destroy +dumptargetinfo +dumpzoneinfo +forcecommand +kill +killplayer +setexperience +aiignore +clearcompletedquest +clearstaticitem +csdumptarget +editstats +emptymailtarget +findobject +findobjetbytemplate +findplayer +findcreature +generatecrafteditem +getgametime +getplayerid +getstationname +gmforcecommand +grantskill +harmfull +harmless +goto +gmweapon +gmrevive +qatool +searchcorpse +setfaction +setfactionstanding +setname +setplayerstate +setrank +setgrievousauthorized +sethue +setinstanceauthorized +setfirstname +setlastname +setplayerappearance +setplayerstate +settef +showfactioninformation +gmclearquest +gmgrantquest +gmspawnship +initializecomponent +combatdatarecord +combatdataclear +combatdatareport +combatdatastop +combatmodecheck +spewcommandqueue +object +createcreature +createspawningelement \ No newline at end of file diff --git a/accesslevels/staff.txt b/accesslevels/staff.txt new file mode 100644 index 00000000..48b6dda2 --- /dev/null +++ b/accesslevels/staff.txt @@ -0,0 +1,7 @@ +invulnerable +teleport +teleportto +teleporttarget +setspeed +gmforcecommand +gmrevive \ No newline at end of file diff --git a/logs/placeHolder.txt b/logs/placeHolder.txt new file mode 100644 index 00000000..e69de29b diff --git a/nge.backup b/nge.backup index 1a761380..3091c7ff 100644 Binary files a/nge.backup and b/nge.backup differ diff --git a/ngengine_public.jar b/ngengine_public.jar index 2a5cd790..9925c80a 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/options.cfg b/options.cfg index c96f5a3b..3e5d1c26 100644 --- a/options.cfg +++ b/options.cfg @@ -1,7 +1,27 @@ +# Toggles the loading of /clientdata/snapshot. +# 1 = Enabled, 0 = Disabled. LOAD.SNAPSHOT_OBJECTS=1 + +# Toggles the loading of /clientdata/buildouts. +# 1 = Enabled, 0 = Disabled. LOAD.BUILDOUT_OBJECTS=0 + +# Toggles the loading of /clinetdata/buildouts for a paticular terrain. +# Specify the terrain. This line should be commented out to be disabled. #LOAD.BUILDOUT_ONLY_FOR="dathomir" + +# Toggles Loading Old/Creating new/Spawning New Resources. +# 1 = On, 0 = Off. LOAD.RESOURCE.SYSTEM=1 -# Misc +# Toggles full wipe of Server Database (Characters, Items, etc.) +# 1 = Enabled, 0 = Disabled. CLEAN.ODB.FOLDERS=0 + +# Toggles Isolation System Spawning at Tatooine 0 0 0 around no NPC's. +# 1 = On, 0 = Off. +DO.ISOLATION.TESTS=0 + +# Toggles GCW Invasions System. +# 1 = On, 0 = Off. +ENABLE.INVASIONS=0 diff --git a/scripts/buffs/banner_buff_bounty_hunter.py b/scripts/buffs/banner_buff_bounty_hunter.py new file mode 100644 index 00000000..3ceeb3b3 --- /dev/null +++ b/scripts/buffs/banner_buff_bounty_hunter.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_critical_niche_all', 5) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_critical_niche_all', 5) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_commando.py b/scripts/buffs/banner_buff_commando.py new file mode 100644 index 00000000..c51d7521 --- /dev/null +++ b/scripts/buffs/banner_buff_commando.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'proc_buff', 1) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'proc_buff', 1) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_entertainer.py b/scripts/buffs/banner_buff_entertainer.py new file mode 100644 index 00000000..624cbcde --- /dev/null +++ b/scripts/buffs/banner_buff_entertainer.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_dodge', 2) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_dodge', 2) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_force_sensitive.py b/scripts/buffs/banner_buff_force_sensitive.py new file mode 100644 index 00000000..c0a1286f --- /dev/null +++ b/scripts/buffs/banner_buff_force_sensitive.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'strength_modified', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'strength_modified', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_medic.py b/scripts/buffs/banner_buff_medic.py new file mode 100644 index 00000000..e01d7147 --- /dev/null +++ b/scripts/buffs/banner_buff_medic.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'constitution_modified', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'constitution_modified', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_officer.py b/scripts/buffs/banner_buff_officer.py new file mode 100644 index 00000000..3adb49d7 --- /dev/null +++ b/scripts/buffs/banner_buff_officer.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'precision_modified', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'precision_modified', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_smuggler.py b/scripts/buffs/banner_buff_smuggler.py new file mode 100644 index 00000000..694c9c9a --- /dev/null +++ b/scripts/buffs/banner_buff_smuggler.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'luck_modified', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'luck_modified', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_spy.py b/scripts/buffs/banner_buff_spy.py new file mode 100644 index 00000000..4500cd97 --- /dev/null +++ b/scripts/buffs/banner_buff_spy.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'agility_modified', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'agility_modified', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/banner_buff_trader.py b/scripts/buffs/banner_buff_trader.py new file mode 100644 index 00000000..ff5f0868 --- /dev/null +++ b/scripts/buffs/banner_buff_trader.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_glancing_blow_all', 100) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_glancing_blow_all', 100) + return + \ No newline at end of file diff --git a/scripts/buffs/barricade_defender.py b/scripts/buffs/barricade_defender.py new file mode 100644 index 00000000..9acc5d3c --- /dev/null +++ b/scripts/buffs/barricade_defender.py @@ -0,0 +1,18 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_dodge', 35) + core.skillModService.addSkillMod(actor, 'display_only_evasion', 5000) + core.skillModService.addSkillMod(actor, 'combat_evasion_value', 50) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_dodge', 35) + core.skillModService.deductSkillMod(actor, 'display_only_evasion', 5000) + core.skillModService.deductSkillMod(actor, 'combat_evasion_value', 50) + return + \ No newline at end of file diff --git a/scripts/buffs/gcw_fatigue.py b/scripts/buffs/gcw_fatigue.py new file mode 100644 index 00000000..2fc75c61 --- /dev/null +++ b/scripts/buffs/gcw_fatigue.py @@ -0,0 +1,25 @@ +import sys +from java.lang import Short + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + + #fatigue = actor.getGCWFatigue() + 1 + #actor.setGCWFatigue(fatigue) + return + +def remove(core, actor, buff): + #if actor.getGCWFatigue()>0: + #fatigue = actor.getGCWFatigue() - 1 + #actor.setGCWFatigue(fatigue) + # Major flaw in Buff system. It does not consider infinite, stackable buffs + # The GCW buff gets automatically removed upon each new stack + # resulting in +1-1 Fatigue, if the fatigue gets set here. + # Only way is to set it, is in the java methods + # and then invent a way so that entertainer can heal this + + return + \ No newline at end of file diff --git a/scripts/buffs/gcw_general_resistance_stack_rebel.py b/scripts/buffs/gcw_general_resistance_stack_rebel.py new file mode 100644 index 00000000..9acc5d3c --- /dev/null +++ b/scripts/buffs/gcw_general_resistance_stack_rebel.py @@ -0,0 +1,18 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_dodge', 35) + core.skillModService.addSkillMod(actor, 'display_only_evasion', 5000) + core.skillModService.addSkillMod(actor, 'combat_evasion_value', 50) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_dodge', 35) + core.skillModService.deductSkillMod(actor, 'display_only_evasion', 5000) + core.skillModService.deductSkillMod(actor, 'combat_evasion_value', 50) + return + \ No newline at end of file diff --git a/scripts/buffs/tower_defender.py b/scripts/buffs/tower_defender.py new file mode 100644 index 00000000..8ca5e20c --- /dev/null +++ b/scripts/buffs/tower_defender.py @@ -0,0 +1,14 @@ +import sys + +def setup(core, actor, buff): + + return + +def add(core, actor, buff): + core.skillModService.addSkillMod(actor, 'expertise_damage_npc', 200) + return + +def remove(core, actor, buff): + core.skillModService.deductSkillMod(actor, 'expertise_damage_npc', -200) + return + \ No newline at end of file diff --git a/scripts/character_builder_terminal.py b/scripts/character_builder_terminal.py index d58927ff..43771be2 100644 --- a/scripts/character_builder_terminal.py +++ b/scripts/character_builder_terminal.py @@ -142,8 +142,9 @@ def travelHandler(owner): window.addHandler(0, '', Trigger.TRIGGER_OK, returnList, travelHandlerCallback) window.addListBoxMenuItem('Tatooine, Mos Eisley', 0) window.addListBoxMenuItem('Dantooine, Jedi Ruins', 1) - window.addListBoxMenuItem('Blank', 2) - window.addListBoxMenuItem('Blank', 3) + window.addListBoxMenuItem('Talus, Dearic Starport', 2) + window.addListBoxMenuItem('Naboo, Keren Starport', 3) + window.addListBoxMenuItem('Tatooine, Bestine Starport', 4) core.suiService.openSUIWindow(window); def travelHandlerCallback(owner, window, eventType, returnList): @@ -158,6 +159,15 @@ def travelHandlerCallback(owner, window, eventType, returnList): if returnList.get(0)=='1': jediRuinsTravel(owner) return + if returnList.get(0)=='2': + GCWDearicTravel(owner) + return + if returnList.get(0)=='3': + GCWKerenTravel(owner) + return + if returnList.get(0)=='4': + GCWBestineTravel(owner) + return return @@ -307,6 +317,9 @@ def miscHandler(owner): window.addListBoxMenuItem('Heroism Jewelry Set', 1) window.addListBoxMenuItem('Belt of Master Bodo Baas', 2) window.addListBoxMenuItem('Starter Equipment Box', 3) + window.addListBoxMenuItem('GCW Banners', 4) + window.addListBoxMenuItem('Bounty Droids', 5) + core.suiService.openSUIWindow(window); def miscHandlerCallback(owner, window, eventType, returnList): @@ -327,6 +340,13 @@ def miscHandlerCallback(owner, window, eventType, returnList): if returnList.get(0)=='3': starterEquipmentBox(owner, inventory) return + if returnList.get(0)=='4': + GCWBanners(owner, inventory) + return + if returnList.get(0)=='5': + bountyDroids(owner, inventory) + return + return def combatLevel(owner): @@ -652,6 +672,21 @@ def jediRuinsTravel(owner): core.simulationService.transferToPlanet(owner, core.terrainService.getPlanetByName("dantooine"), position, owner.getOrientation(), None) return +def GCWDearicTravel(owner): + position = Point3D(264, 4, -2950) + core.simulationService.transferToPlanet(owner, core.terrainService.getPlanetByName("talus"), position, owner.getOrientation(), None) + return + +def GCWKerenTravel(owner): + position = Point3D(1366, 13, 2747) + core.simulationService.transferToPlanet(owner, core.terrainService.getPlanetByName("naboo"), position, owner.getOrientation(), None) + return + +def GCWBestineTravel(owner): + position = Point3D(-1385,12, -3597) + core.simulationService.transferToPlanet(owner, core.terrainService.getPlanetByName("tatooine"), position, owner.getOrientation(), None) + return + def surveyDevices(owner, inventory): mineralSurveyTool = core.objectService.createObject("object/tangible/survey_tool/shared_survey_tool_mineral.iff", owner.getPlanet()) chemicalSurveyTool = core.objectService.createObject("object/tangible/survey_tool/shared_survey_tool_inorganic.iff", owner.getPlanet()) @@ -668,4 +703,29 @@ def surveyDevices(owner, inventory): inventory.add(windSurveyTool) inventory.add(solarSurveyTool) return - \ No newline at end of file + +def GCWBanners(owner, inventory): + + gcwBanner1 = core.objectService.createObject('object/tangible/gcw/pvp_rank_rewards/shared_rebel_battle_banner.iff', owner.getPlanet()) + gcwBanner1.setStfFilename('static_item_n') + gcwBanner1.setStfName('item_pvp_captain_battle_banner_rebel_reward_04_01') + gcwBanner1.setDetailFilename('static_item_d') + gcwBanner1.setDetailName('item_pvp_captain_battle_banner_rebel_reward_04_01') + inventory.add(gcwBanner1) + gcwBanner2 = core.objectService.createObject('object/tangible/gcw/pvp_rank_rewards/shared_imperial_battle_banner.iff', owner.getPlanet()) + gcwBanner2.setStfFilename('static_item_n') + gcwBanner2.setStfName('item_pvp_captain_battle_banner_imperial_reward_04_01') + gcwBanner2.setDetailFilename('static_item_d') + gcwBanner2.setDetailName('item_pvp_captain_battle_banner_imperial_reward_04_01') + inventory.add(gcwBanner2) + return + +def bountyDroids(owner, inventory): + seekers = core.objectService.createObject('object/tangible/mission/shared_mission_bounty_droid_seeker.iff', owner.getPlanet()) + seekers.setUses(20) + inventory.add(seekers) + + probe = core.objectService.createObject('object/tangible/mission/shared_mission_bounty_droid_probot.iff', owner.getPlanet()) + probe.setUses(20) + inventory.add(probe) + return \ No newline at end of file diff --git a/scripts/commands/giveitem.py b/scripts/commands/giveitem.py index 65791788..0b9d2642 100644 --- a/scripts/commands/giveitem.py +++ b/scripts/commands/giveitem.py @@ -9,10 +9,7 @@ def run(core, actor, target, commandString): arg1 = commandArgs[0] if len(commandArgs) > 1: arg2 = commandArgs[1] - - if actor.getClient() and actor.getClient().isGM() == False: - return - + if not commandString.startswith('object/tangible') and not commandString.startswith('object/weapon'): return diff --git a/scripts/commands/pvp.py b/scripts/commands/pvp.py index 34f6c5ff..cc30e82b 100644 --- a/scripts/commands/pvp.py +++ b/scripts/commands/pvp.py @@ -10,7 +10,7 @@ def setup(): def run(core, actor, target, commandString): faction = actor.getFaction() factionStatus = actor.getFactionStatus() - + if actor.getPvpStatus(PvpStatus.GoingOvert) or actor.getPvpStatus(PvpStatus.GoingCovert): actor.sendSystemMessage('@faction_recruiter:pvp_status_changing', 0) return @@ -18,9 +18,10 @@ def run(core, actor, target, commandString): actor.sendSystemMessage('@gcw:pvp_advanced_region_cannot_go_covert', 0) return - if commandString != '' and commandString != faction: + if commandString != '' and commandString != faction and len(faction)!=0: if commandString == 'rebel' or commandString == 'imperial' or commandString == 'neutral': - if faction != 'neutral': + + if faction != 'neutral' and len(faction)!=0: actor.sendSystemMessage('@faction_recruiter:sui_resig_complete_in_5', 0) if actor.getFactionStatus() == FactionStatus.SpecialForces: @@ -37,7 +38,7 @@ def run(core, actor, target, commandString): if commandString == 'neutral' or commandString == 'resign': time.sleep(1) - actor.setFaction('') + actor.setFaction('') # ??? actor.sendSystemMessage('@faction_recruiter:resign_complete', 0) return @@ -45,6 +46,15 @@ def run(core, actor, target, commandString): actor.setFaction(commandString) return + #This can be removed if player is required to see the recruiter first + if faction == '': + actor.setFactionStatus(FactionStatus.Combatant) # Must be! otherwise updatePVPstatus will be called with onLeave! + actor.setFaction(commandString) + player = actor.getSlottedObject("ghost") + if player.getCurrentRank()==0: + player.setCurrentRank(1); + faction = commandString + if faction == 'neutral' or faction == '': actor.sendSystemMessage('@faction_recruiter:not_aligned', 0) return @@ -53,10 +63,11 @@ def run(core, actor, target, commandString): actor.sendSystemMessage('@faction_recruiter:on_leave_to_covert', 0) actor.setPvpStatus(PvpStatus.GoingCovert, True) time.sleep(1) - actor.setFactionStatus(FactionStatus.Combatant) actor.setPvpStatus(PvpStatus.GoingCovert, False) + actor.setFactionStatus(FactionStatus.Combatant) actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) actor.updatePvpStatus() + core.factionService.updatePVPFromNearbyNPCs(actor, actor.getClient()) return if factionStatus == FactionStatus.Combatant: @@ -65,8 +76,8 @@ def run(core, actor, target, commandString): time.sleep(30) if core.gcwService.isInPvpZone(actor): return - actor.setFactionStatus(FactionStatus.SpecialForces) actor.setPvpStatus(PvpStatus.GoingOvert, False) + actor.setFactionStatus(FactionStatus.SpecialForces) actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) actor.updatePvpStatus() return diff --git a/scripts/commands/setgodmode.py b/scripts/commands/setgodmode.py index e00e103d..dd42674f 100644 --- a/scripts/commands/setgodmode.py +++ b/scripts/commands/setgodmode.py @@ -2,6 +2,7 @@ import sys from engine.resources.scene import Point3D from protocol.swg import ObjControllerMessage from protocol.swg import UnknownAbilityPacket +from protocol.swg import PlayClientEffectLocMessage from engine.resources.objects import SWGObject from java.awt.datatransfer import StringSelection from java.awt.datatransfer import Clipboard @@ -35,16 +36,6 @@ def run(core, actor, target, commandString): if len(commandArgs) > 5: arg5 = commandArgs[5] - if not command: - return - - if actor.getClient().isGM() is False: - return - - if playerObject.getGodLevel() == 0: - actor.addAbility("admin") - playerObject.setGodLevel(50) - if command == 'giveExperience' and arg1: core.playerService.giveExperience(actor, int(arg1)) @@ -191,6 +182,85 @@ def run(core, actor, target, commandString): actor.setPosture(0) actor.setSpeedMultiplierBase(1) actor.setTurnRadius(1) + + elif command == 'checkai': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + actor.sendSystemMessage('Checking AI handling for unit ' + latarget.getCustomName(), 0) + core.aiService.setCheckAI(latarget) + + elif command == 'checkaitarget': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + if latarget.getAttachment('AI'): + if latarget.getAttachment('AI').getFollowObject(): + actor.sendSystemMessage('Checking AI target ' + latarget.getAttachment('AI').getFollowObject().getTemplate(), 0) + + elif command == 'checkaistate': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + if latarget.getAttachment('AI'): + if latarget.getAttachment('AI').getCurrentState(): + actor.sendSystemMessage('Checking AI state ' + latarget.getAttachment('AI').getCurrentState().getClass().getName(), 0) + + elif command == 'checkairepos': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + if latarget.getAttachment('AI'): + if latarget.getAttachment('AI').getRepositionStartTime()(): + actor.sendSystemMessage('Checking AI state ' + latarget.getAttachment('AI').getRepositionStartTime(), 0) + + elif command == 'checkaiprog': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + if latarget.getAttachment('AI'): + actor.sendSystemMessage('Checking AI progression %s' % latarget.getAttachment('AI').getProgressionMarker(), 0) + + elif command == 'checkwithdrawn': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + if latarget.getAttachment('isWithdrawn'): + actor.sendSystemMessage('Checking AIisWithdrawn %s' % latarget.getAttachment('isWithdrawn'), 0) + + elif command == 'showbitmask': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + actor.sendSystemMessage('Optionsbitmask for unit ' + latarget.getCustomName() + ' is %s' % latarget.getOptionsBitmask(), 0) + + elif command == 'spawninst': + + #String campTemplate = "object/building/poi/shared_gcw_rebel_clone_tent_small.iff"; // LOL why doesn't this spawn?!?!?! + inst = core.objectService.createObject(arg1, 0, actor.getPlanet(), actor.getWorldPosition(), actor.getOrientation()) + if inst: + #TangibleObject inst = (TangibleObject) core.objectService.createObject(campTemplate, 0, core.terrainService.getPlanetByName("talus"), new Point3D(-890,9, -2994), quaternion) + core.simulationService.add(inst, inst.getPosition().x, inst.getPosition().z, True) + positionY = core.terrainService.getHeight(inst.getPlanetId(), inst.getPosition().x, inst.getPosition().z) + instpos = Point3D(inst.getPosition().x,positionY+2, inst.getPosition().z) + inst.setPosition(instpos) + + elif command == 'los': + latargetID = long(actor.getIntendedTarget()) + latarget = core.objectService.getObject(latargetID) + los = core.simulationService.checkLineOfSight(actor, latarget) + if los: + actor.sendSystemMessage('Line of sight between player and target', 0) + else: + actor.sendSystemMessage('NO Line of sight between player and target', 0) + + elif command == 'playfx': + effectFile = arg1 + cEffMsg = PlayClientEffectLocMessage(effectFile, actor.getPlanet().getName(), actor.getPosition()) + actor.getClient().getSession().write(cEffMsg.serialize()) + + elif command == 'toinvasion': + invasionplanet = core.invasionService.getInvasionPlanetName() + position = Point3D(float(1366), float(13), float(2747)) + if invasionplanet == 'talus': + position = Point3D(float(264), float(4), float(-2950)) + if invasionplanet == 'tatooine': + position = Point3D(float(-1385), float(12), float(-3597)) + + core.simulationService.transferToPlanet(actor, core.terrainService.getPlanetByName(invasionplanet), position, actor.getOrientation(), None) elif command == 'unknownAbilityPacket' and arg1: packet = UnknownAbilityPacket(arg1) diff --git a/scripts/faction/imperial.py b/scripts/faction/imperial.py index b5bc8cc0..f7b1232c 100644 --- a/scripts/faction/imperial.py +++ b/scripts/faction/imperial.py @@ -1,6 +1,8 @@ import sys def isAlly(ally): + if ally == 'imperial': + return 1 return 0 def isEnemy(enemy): diff --git a/scripts/faction/rebel.py b/scripts/faction/rebel.py index 0d685a6a..f435ab8c 100644 --- a/scripts/faction/rebel.py +++ b/scripts/faction/rebel.py @@ -1,6 +1,8 @@ import sys def isAlly(ally): + if ally == 'rebel': + return 1 return 0 def isEnemy(enemy): diff --git a/scripts/mobiles/generic/faction/imperial/elite_imperial_stormtrooper_90.py b/scripts/mobiles/generic/faction/imperial/elite_imperial_stormtrooper_90.py new file mode 100644 index 00000000..e1fa305b --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/elite_imperial_stormtrooper_90.py @@ -0,0 +1,43 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('crackdown_stormtrooper_hard') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_dressed_stormtrooper_black_white.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_black.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_white.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('elite_imperial_stormtrooper_90', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py b/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py new file mode 100644 index 00000000..02c3d8a9 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py @@ -0,0 +1,43 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('fbase_imperial_colonel_extreme') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(False) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setNoAI(True) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_colonel_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_defensive_quest_officer', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py new file mode 100644 index 00000000..99e1234c --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('at_at') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_atat.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_at_at', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py new file mode 100644 index 00000000..b6e60b36 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py @@ -0,0 +1,44 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_st_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + + templates = Vector() + templates.add('object/mobile/shared_atst.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() # object/weapon/ranged/turret/shared_turret_heat.iff object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 2.0, 55, 'energy') + #weapontemplate = WeaponTemplate('object/weapon/ranged/rifle/shared_rifle_t21.iff', WeaponType.RIFLE, 1.0, 24, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('gcw_atst_attack_tower') #gcw_atst_attack_tower #rangedShot + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_at_st', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_captain.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_captain.py new file mode 100644 index 00000000..5fa32db5 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_captain.py @@ -0,0 +1,44 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_imperial_captain') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.NORMAL) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(False) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setNoAI(True) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_captain_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_captain', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_demoralized_soldier.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_demoralized_soldier.py new file mode 100644 index 00000000..62962707 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_demoralized_soldier.py @@ -0,0 +1,45 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCustomName('A demoralized imperial soldier') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_stormtrooper_black_white.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_black.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_white.iff') + templates.add('object/mobile/shared_dark_trooper.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_demoralized_soldier', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_disabled_atst.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_disabled_atst.py new file mode 100644 index 00000000..9b9040b8 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_disabled_atst.py @@ -0,0 +1,45 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCustomName('A disabled AT-ST') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_atst.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() # object/weapon/ranged/turret/shared_turret_heat.iff object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 2.0, 55, 'energy') + #weapontemplate = WeaponTemplate('object/weapon/ranged/rifle/shared_rifle_t21.iff', WeaponType.RIFLE, 1.0, 24, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('gcw_atst_attack_tower') #gcw_atst_attack_tower #rangedShot + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_disabled_atst', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py new file mode 100644 index 00000000..7b19a8cc --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py @@ -0,0 +1,45 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_imperial_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.INVULNERABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_general_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_soldier_cl90.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_soldier_cl90.py new file mode 100644 index 00000000..6ad094e2 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_soldier_cl90.py @@ -0,0 +1,44 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('crackdown_stormtrooper_hard') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_dressed_stormtrooper_black_white.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_black.iff') + templates.add('object/mobile/shared_dressed_stormtrooper_white_white.iff') + templates.add('object/mobile/shared_dark_trooper.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_soldier_cl90', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_offensive_invasion_general.py b/scripts/mobiles/generic/faction/imperial/imp_offensive_invasion_general.py new file mode 100644 index 00000000..b13bdac1 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_offensive_invasion_general.py @@ -0,0 +1,45 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_offensive_imperial_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_general_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_offensive_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/gcw_city_rebel_soldier.py b/scripts/mobiles/generic/faction/rebel/gcw_city_rebel_soldier.py new file mode 100644 index 00000000..c6c75763 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/gcw_city_rebel_soldier.py @@ -0,0 +1,45 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('cheerleader_rebel_commando_hard') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(True) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_commando_human_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_human_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_rodian_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_twilek_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_zabrak_female_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('gcw_city_rebel_soldier', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py b/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py new file mode 100644 index 00000000..4570cb07 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py @@ -0,0 +1,46 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('crackdown_rebel_colonel') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setNoAI(True) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_human_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_human_male_02.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_moncal_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_rodian_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_rodian_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_zabrak_male_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_defensive_quest_officer', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py new file mode 100644 index 00000000..64c7258d --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py @@ -0,0 +1,43 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_xt_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + + templates = Vector() + templates.add('object/mobile/shared_atxt.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('gcw_atst_attack_tower') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_at_xt', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_captain.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_captain.py new file mode 100644 index 00000000..9ef28ca6 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_captain.py @@ -0,0 +1,46 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_rebel_captain') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setNoAI(True) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_army_captain_bothan_male.iff') + templates.add('object/mobile/shared_dressed_rebel_army_captain_human_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_army_captain_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_army_captain_trandoshan_female.iff') + templates.add('object/mobile/shared_dressed_rebel_army_captain_twk_male.iff') + templates.add('object/mobile/shared_dressed_rebel_army_captain_zabrak_female.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_captain', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_demoralized_soldier.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_demoralized_soldier.py new file mode 100644 index 00000000..8af3c215 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_demoralized_soldier.py @@ -0,0 +1,46 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('A demoralized rebel soldier') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(True) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_commando_human_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_human_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_rodian_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_twilek_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_commando_zabrak_female_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_demoralized_soldier', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_disabled_atxt.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_disabled_atxt.py new file mode 100644 index 00000000..bbc7b026 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_disabled_atxt.py @@ -0,0 +1,44 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCustomName('A disabled AT-XT') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_atxt.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('gcw_atst_attack_tower') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_disabled_atxt', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py new file mode 100644 index 00000000..db7458e8 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py @@ -0,0 +1,48 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_rebel_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.INVULNERABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_general_human_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_human_female_02.iff') + templates.add('object/mobile/shared_dressed_rebel_general_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_old_twilek_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rieekan_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rodian_female_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py new file mode 100644 index 00000000..b6e1d362 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('rebel_battle_droid') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_hailfire_droid.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/droid/shared_droid_rocket_launcher.iff', WeaponType.RIFLE, 1.0, 55, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('gcw_rocket_launch') #fireRocketLauncher #gcw_atst_attack_tower + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_hailfire_droid', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_offensive_invasion_general.py b/scripts/mobiles/generic/faction/rebel/rebel_offensive_invasion_general.py new file mode 100644 index 00000000..c627f8c8 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_offensive_invasion_general.py @@ -0,0 +1,48 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_offensive_rebel_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_general_human_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_human_female_02.iff') + templates.add('object/mobile/shared_dressed_rebel_general_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_old_twilek_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rieekan_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rodian_female_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_offensive_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/tatooine/mos_eisley_police_officer.py b/scripts/mobiles/tatooine/mos_eisley_police_officer.py index 2e7a335f..99bec986 100644 --- a/scripts/mobiles/tatooine/mos_eisley_police_officer.py +++ b/scripts/mobiles/tatooine/mos_eisley_police_officer.py @@ -19,6 +19,7 @@ def addTemplate(core): mobileTemplate.setAssistRange(0) mobileTemplate.setStalker(True) mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + mobileTemplate.setRespawnTime(5) templates = Vector() templates.add('object/mobile/shared_dressed_eisley_officer_aqualish_female_01.iff') diff --git a/scripts/mobiles/tatooine/mos_eisley_police_sergeant.py b/scripts/mobiles/tatooine/mos_eisley_police_sergeant.py index ad35c65e..f92baa28 100644 --- a/scripts/mobiles/tatooine/mos_eisley_police_sergeant.py +++ b/scripts/mobiles/tatooine/mos_eisley_police_sergeant.py @@ -19,6 +19,7 @@ def addTemplate(core): mobileTemplate.setAssistRange(0) mobileTemplate.setStalker(True) mobileTemplate.setOptionsBitmask(Options.ATTACKABLE) + mobileTemplate.setRespawnTime(5) templates = Vector() templates.add('object/mobile/shared_dressed_eisley_officer_bothan_female_01.iff') diff --git a/scripts/object/installation/turret/gcw/adv_turret_block_med_heat.py b/scripts/object/installation/turret/gcw/adv_turret_block_med_heat.py index ccad8904..04e68ef9 100644 --- a/scripts/object/installation/turret/gcw/adv_turret_block_med_heat.py +++ b/scripts/object/installation/turret/gcw/adv_turret_block_med_heat.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useTurret(owner, target); return \ No newline at end of file diff --git a/scripts/object/installation/turret/gcw/adv_turret_dish_large_heat.py b/scripts/object/installation/turret/gcw/adv_turret_dish_large_heat.py index ccad8904..04e68ef9 100644 --- a/scripts/object/installation/turret/gcw/adv_turret_dish_large_heat.py +++ b/scripts/object/installation/turret/gcw/adv_turret_dish_large_heat.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useTurret(owner, target); return \ No newline at end of file diff --git a/scripts/object/installation/turret/gcw/adv_turret_dish_sm_heat.py b/scripts/object/installation/turret/gcw/adv_turret_dish_sm_heat.py index ccad8904..04e68ef9 100644 --- a/scripts/object/installation/turret/gcw/adv_turret_dish_sm_heat.py +++ b/scripts/object/installation/turret/gcw/adv_turret_dish_sm_heat.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useTurret(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/destructible/gcw_city_construction_beacon.py b/scripts/object/tangible/destructible/gcw_city_construction_beacon.py index ccad8904..52398bbc 100644 --- a/scripts/object/tangible/destructible/gcw_city_construction_beacon.py +++ b/scripts/object/tangible/destructible/gcw_city_construction_beacon.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.usePylon(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/destructible/gcw_imperial_barricade.py b/scripts/object/tangible/destructible/gcw_imperial_barricade.py index ccad8904..3fce58db 100644 --- a/scripts/object/tangible/destructible/gcw_imperial_barricade.py +++ b/scripts/object/tangible/destructible/gcw_imperial_barricade.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useBarricade(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/destructible/gcw_imperial_tower.py b/scripts/object/tangible/destructible/gcw_imperial_tower.py index ccad8904..287f3df3 100644 --- a/scripts/object/tangible/destructible/gcw_imperial_tower.py +++ b/scripts/object/tangible/destructible/gcw_imperial_tower.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useTower(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/destructible/gcw_rebel_barricade.py b/scripts/object/tangible/destructible/gcw_rebel_barricade.py index ccad8904..3fce58db 100644 --- a/scripts/object/tangible/destructible/gcw_rebel_barricade.py +++ b/scripts/object/tangible/destructible/gcw_rebel_barricade.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useBarricade(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/destructible/gcw_rebel_tower.py b/scripts/object/tangible/destructible/gcw_rebel_tower.py index ccad8904..287f3df3 100644 --- a/scripts/object/tangible/destructible/gcw_rebel_tower.py +++ b/scripts/object/tangible/destructible/gcw_rebel_tower.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.useTower(owner, target); return \ No newline at end of file diff --git a/scripts/object/tangible/gcw/pvp_rank_rewards/imperial_battle_banner.py b/scripts/object/tangible/gcw/pvp_rank_rewards/imperial_battle_banner.py index ccad8904..0a4b00e0 100644 --- a/scripts/object/tangible/gcw/pvp_rank_rewards/imperial_battle_banner.py +++ b/scripts/object/tangible/gcw/pvp_rank_rewards/imperial_battle_banner.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'item/gcwbanner') return \ No newline at end of file diff --git a/scripts/object/tangible/gcw/pvp_rank_rewards/rebel_battle_banner.py b/scripts/object/tangible/gcw/pvp_rank_rewards/rebel_battle_banner.py index ccad8904..0a4b00e0 100644 --- a/scripts/object/tangible/gcw/pvp_rank_rewards/rebel_battle_banner.py +++ b/scripts/object/tangible/gcw/pvp_rank_rewards/rebel_battle_banner.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'item/gcwbanner') return \ No newline at end of file diff --git a/scripts/object/tangible/terminal/terminal_gcw_imp_def.py b/scripts/object/tangible/terminal/terminal_gcw_imp_def.py index ccad8904..046f166e 100644 --- a/scripts/object/tangible/terminal/terminal_gcw_imp_def.py +++ b/scripts/object/tangible/terminal/terminal_gcw_imp_def.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.supplyTerminalSUI(owner, 0); return \ No newline at end of file diff --git a/scripts/object/tangible/terminal/terminal_gcw_imp_offensiv.py b/scripts/object/tangible/terminal/terminal_gcw_imp_offensiv.py index ccad8904..142710d8 100644 --- a/scripts/object/tangible/terminal/terminal_gcw_imp_offensiv.py +++ b/scripts/object/tangible/terminal/terminal_gcw_imp_offensiv.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.supplyOffensiveTerminalSUI(owner, 0); return \ No newline at end of file diff --git a/scripts/object/tangible/terminal/terminal_gcw_reb_def.py b/scripts/object/tangible/terminal/terminal_gcw_reb_def.py index ccad8904..046f166e 100644 --- a/scripts/object/tangible/terminal/terminal_gcw_reb_def.py +++ b/scripts/object/tangible/terminal/terminal_gcw_reb_def.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.supplyTerminalSUI(owner, 0); return \ No newline at end of file diff --git a/scripts/object/tangible/terminal/terminal_gcw_reb_offensiv.py b/scripts/object/tangible/terminal/terminal_gcw_reb_offensiv.py index ccad8904..142710d8 100644 --- a/scripts/object/tangible/terminal/terminal_gcw_reb_offensiv.py +++ b/scripts/object/tangible/terminal/terminal_gcw_reb_offensiv.py @@ -1,4 +1,7 @@ -import sys - def setup(core, object): + object.setAttachment('radial_filename', 'object/usable') + return + +def use(core, owner, target): + core.invasionService.supplyOffensiveTerminalSUI(owner, 0); return \ No newline at end of file diff --git a/scripts/radial/item/gcwbanner.py b/scripts/radial/item/gcwbanner.py new file mode 100644 index 00000000..abcee8c7 --- /dev/null +++ b/scripts/radial/item/gcwbanner.py @@ -0,0 +1,49 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, '')) + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 15, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + handleBanner(core, owner, target, option) + if option == 15 and target: + core.objectService.destroyObject(target) + return + +def handleBanner(core, owner, bannerinventoryobject, option): + + # check if faction alignment matches + if len(owner.getFaction()) == 0: + owner.sendSystemMessage('You are not aligned appropriately to use this banner' , 0) + return + if bannerinventoryobject.getTemplate().find(owner.getFaction()) == -1: + owner.sendSystemMessage('You are not aligned appropriately to use this banner' , 0) + return + + # check if banner object is not already spawned + #if bannerinventoryobject.getAttachment('BannerSpawned'): + #owner.sendSystemMessage('Banner already spawned' , 0) + #return + + # spawn banner object + stcSvc = core.staticService + banner = stcSvc.spawnObject(bannerinventoryobject.getTemplate(), owner.getPlanet().getName(), long(0), owner.getWorldPosition().x + 1, owner.getWorldPosition().y, owner.getWorldPosition().z, owner.getOrientation().w, owner.getOrientation().x, owner.getOrientation().y, owner.getOrientation().z) + if len(bannerinventoryobject.getStfFilename())>0: + banner.setStfFilename(bannerinventoryobject.getStfFilename()) + if len(bannerinventoryobject.getStfName())>0: + banner.setStfName(bannerinventoryobject.getStfName()) + if len(bannerinventoryobject.getDetailFilename())>0: + banner.setDetailFilename(bannerinventoryobject.getDetailFilename()) + if len(bannerinventoryobject.getDetailName())>0: + #banner.setDetailDescription(bannerinventoryobject.getBaseline(6).get("detailedDescription").getString()) + banner.setDetailName(bannerinventoryobject.getDetailName()) + bannerinventoryobject.setAttachment('BannerSpawned', True) + + # start buffing process + core.buffService.initiateBannerBuffProcess(owner, banner) + + return \ No newline at end of file diff --git a/scripts/radial/terminal/city_maintenance_terminal.py b/scripts/radial/terminal/city_maintenance_terminal.py index 50259cfa..b16bb4be 100644 --- a/scripts/radial/terminal/city_maintenance_terminal.py +++ b/scripts/radial/terminal/city_maintenance_terminal.py @@ -34,7 +34,7 @@ def createRadial(core, owner, target, radials): if owner.getPlayerObject().getCitizenship() != 3 and core.playerCityService.getPlayerCity(owner) == city: radials.add(RadialOptions(2, 230, 0, '@city/city:revoke_citizenship')) - if owner.getClient().isGM(): + if core.adminService.getAccessLevelFromDB(actor.getClient().getAccountId()) is not None: radials.add(RadialOptions(2, 231, 0, 'Add 10 citizens')) radials.add(RadialOptions(2, 232, 0, 'Deduct 10 citizens')) diff --git a/src/main/NGECore.java b/src/main/NGECore.java index a23d5d75..1bde5b9e 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -65,6 +65,7 @@ import services.ConversationService; import services.EntertainmentService; import services.GroupService; import services.housing.HousingService; +import services.AdminService; import services.BrowserService; import services.InstanceService; import services.LoginService; @@ -91,6 +92,7 @@ import services.command.CommandService; import services.equipment.EquipmentService; import services.gcw.FactionService; import services.gcw.GCWService; +import services.gcw.InvasionService; import services.GuildService; import services.LoginService; import services.map.MapService; @@ -153,9 +155,11 @@ public class NGECore { private static NGECore instance; private Config config = null; + private Config options = null; private String motd = ""; private volatile boolean isShuttingDown = false; private long galacticTime = System.currentTimeMillis(); + private int galaxyStatus = -1; private ConcurrentHashMap clients = new ConcurrentHashMap(); @@ -212,6 +216,8 @@ public class NGECore { public PetService petService; public BrowserService browserService; //public BattlefieldService battlefieldService; + public InvasionService invasionService; + public AdminService adminService; // Login Server public NetworkDispatch loginDispatch; @@ -269,11 +275,15 @@ public class NGECore { config = DefaultConfig.getConfig(); } - Config options = new Config(); + options = new Config(); options.setFilePath("options.cfg"); - boolean optionsConfigLoaded = options.loadConfigFile(); - - if (optionsConfigLoaded && options.getInt("CLEAN.ODB.FOLDERS") > 0 || getExcludedDevelopers().contains(System.getProperty("user.name"))){ + if (!(options.loadConfigFile())) { + System.err.println("Failed to load options.cfg!"); + options = DefaultConfig.getConfig(); + } + + //if (optionsConfigLoaded && options.getInt("CLEAN.ODB.FOLDERS") > 0 || getExcludedDevelopers().contains(System.getProperty("user.name"))){ + if (options.getInt("CLEAN.ODB.FOLDERS") > 0){ File baseFolder = new File("./odb"); if (baseFolder.isDirectory()) { @@ -354,7 +364,7 @@ public class NGECore { reverseEngineeringService = new ReverseEngineeringService(this); petService = new PetService(this); - if (optionsConfigLoaded && options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { + if (options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { surveyService = new SurveyService(this); resourceService = new ResourceService(this); } @@ -373,6 +383,7 @@ public class NGECore { spawnService = new SpawnService(this); aiService = new AIService(this); missionService = new MissionService(this); + invasionService = new InvasionService(this); // Ping Server @@ -427,8 +438,9 @@ public class NGECore { zoneDispatch.addService(staticService); zoneDispatch.addService(reverseEngineeringService); zoneDispatch.addService(petService); + zoneDispatch.addService(invasionService); - if (optionsConfigLoaded && options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { + if (options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { zoneDispatch.addService(surveyService); zoneDispatch.addService(resourceService); } @@ -493,13 +505,10 @@ public class NGECore { terrainService.addPlanet(43, "space_tatooine", "terrain/space_tatooine.trn", true); terrainService.addPlanet(44, "space_tatooine_2", "terrain/space_tatooine_2.trn", true); terrainService.addPlanet(45, "space_yavin4", "terrain/space_yavin4.trn", true);*/ - //PSWG New Content Terrains (WARNING Keep commented out unless you have the current build of kaas!) - - //terrainService.addPlanet(46, "kaas", "terrain/kaas.trn", true); - + //end terrainList - if (optionsConfigLoaded && options.getInt("LOAD.RESOURCE.SYSTEM") > 0) { + if (options.getInt("LOAD.RESOURCE.SYSTEM") > 0) { resourceService.loadResources(); } @@ -557,6 +566,7 @@ public class NGECore { browserService = new BrowserService(this); //battlefieldService = new BattlefieldService(this); + adminService = new AdminService(this); DevLogQueuer devLogQueuer = new DevLogQueuer(); @@ -644,6 +654,7 @@ public class NGECore { public void setGalaxyStatus(int statusId) { + galaxyStatus = statusId; int galaxyId = config.getInt("GALAXY_ID"); try { @@ -657,6 +668,10 @@ public class NGECore { } + public int getGalaxyStatus() { + return galaxyStatus; + } + /* * ---------- Getter methods for NGECore ---------- */ @@ -852,10 +867,14 @@ public class NGECore { public Vector getExcludedDevelopers(){ Vector excludedDevelopers = new Vector(); - excludedDevelopers.add("Charon"); + //excludedDevelopers.add("Charon"); // Feel free to add your OS user account name here to exclude yourself from loading buildouts and snapshots // without having to change options.cfg all the time return excludedDevelopers; } + + public Config getOptions() { + return options; + } } diff --git a/src/protocol/swg/LoginClusterStatus.java b/src/protocol/swg/LoginClusterStatus.java index 725a8c8b..05e0a0c0 100644 --- a/src/protocol/swg/LoginClusterStatus.java +++ b/src/protocol/swg/LoginClusterStatus.java @@ -22,8 +22,13 @@ package protocol.swg; import java.nio.ByteOrder; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.TimeZone; +import main.NGECore; + import org.apache.mina.core.buffer.IoBuffer; import engine.clients.Client; @@ -50,8 +55,8 @@ public class LoginClusterStatus extends SWGMessage { } public void addServer(int galaxyID, String serverIP, int serverPort, int pingPort, int maxCharacters, int status, int recommended, int population, Client client) { IoBuffer result = IoBuffer.allocate(39 + serverIP.length()).order(ByteOrder.LITTLE_ENDIAN); - int populationStatus = 0; + result.putInt(galaxyID); result.put(getAsciiString(serverIP)); result.putShort((short)serverPort); @@ -66,11 +71,10 @@ public class LoginClusterStatus extends SWGMessage { populationStatus = 6; status = 3; } - if(status == 3 && client.isGM()) + if(status == 3 && !(NGECore.getInstance().adminService.getAccessLevelFromDB(client.getAccountId()) == null) ) // Ziggy - admins can enter Locked galaxies status = 2; result.putInt(populationStatus); // 0 = very light, 1 = light, 2 = medium , 3 = heavy, 4 = very heavy, 5 = extremely heavy, 6 = full result.putInt(maxCharacters); - //result.putInt(0xFFFF8F80); // Distance? result.putInt(timeZone.getRawOffset() / 3600000); result.putInt(status); result.put((byte)recommended); diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index ff025def..9fb333f9 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -78,6 +78,7 @@ public class ObjControllerMessage extends SWGMessage { public static final int RESOURCE_WEIGHTS = 0x0207; public static final int MISSION_ACCEPT_RESPONSE = 0x00FA; public static final int MISSION_ABORT_RESPONSE = 0x0142; + public static final int QUEST_TASK_TIMER_MESSAGE = 0x0441; public ObjControllerMessage() { diff --git a/src/protocol/swg/ResourceListForSurveyMessage.java b/src/protocol/swg/ResourceListForSurveyMessage.java index a7dd2b68..1b95f623 100644 --- a/src/protocol/swg/ResourceListForSurveyMessage.java +++ b/src/protocol/swg/ResourceListForSurveyMessage.java @@ -25,7 +25,6 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; -import java.util.Vector; import main.NGECore; diff --git a/src/protocol/swg/SUICreateTimerBar.java b/src/protocol/swg/SUICreateTimerBar.java new file mode 100644 index 00000000..456f18ab --- /dev/null +++ b/src/protocol/swg/SUICreateTimerBar.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg; + +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +import org.apache.mina.core.buffer.IoBuffer; + +@SuppressWarnings("unused") +public class SUICreateTimerBar extends SWGMessage{ + + private String script; + private int windowId; + private int startCount; + private int digitCount; + private List digits = new ArrayList(); + String prompt; + + public SUICreateTimerBar(String script, int windowId, String prompt, int startCount) { + + this.script = script; + this.windowId = windowId; + this.startCount = startCount; + this.prompt = prompt; + + digitCount = 3; + if (startCount>9) + digitCount = 4; + + while (startCount > 0) { + int d = startCount / 10; + int k = startCount - d * 10; + startCount = d; + digits.add((int)(Integer.toString(k).charAt(0))); + //System.out.println("digit: "+Integer.toHexString((int)(Integer.toString(k).charAt(0)))); + } +// digits.add(0x39); +// digits.add(0x31); + } + + public void deserialize(IoBuffer data) { + + } + + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); + + result.putShort((short) 2); + result.putInt(0xD44B7259); + + result.putInt(windowId); + result.put(getAsciiString(script)); + result.putInt(5); + result.putInt(5); + result.put((byte)0); + result.putInt(3); + result.putShort((short)0); + result.putShort((short)1); + result.put((byte)9); + + result.put(getAsciiString("modifySlot")); + result.putInt(5); + result.put((byte)0); + result.putInt(3); + result.putShort((short)0); + result.putShort((short)1); + result.put((byte)0xA); + result.put(getAsciiString("modifySlot")); + result.put((byte)3); + result.putInt(1); + + result.put(getUnicodeString(prompt)); + + result.putInt(2); + + result.put(getAsciiString("comp.text")); + result.put(getAsciiString("Text")); + + result.put((byte)3); + result.putInt(1); + + result.put(getUnicodeString("quest_countdown_timer")); + + result.putInt(2); + + result.put(getAsciiString("bg.caption.lblTitle")); + result.put(getAsciiString("Text")); + + + result.put((byte)3); + result.putInt(1); + result.putInt(digitCount); + + result.putShort((short)0x30); + result.putShort((short)0x2C); + for (int i=digits.size()-1;i>=0;i--) + result.putShort((short)((int)digits.get(i))); + + result.putInt(2); + result.put(getAsciiString("this")); + result.put(getAsciiString("countdownTimerTimeValue")); + + result.putLong(0); + result.putInt(0x7F7FFFFF); + result.putInt(0x7F7FFFFF); + result.putInt(0x7F7FFFFF); + result.putInt(0); + + int size = result.position(); + result = IoBuffer.allocate(size).put(result.array(), 0, size); + + return result.flip(); + } +} diff --git a/src/protocol/swg/objectControllerObjects/DataTransform.java b/src/protocol/swg/objectControllerObjects/DataTransform.java index 3b8381e5..62b698b3 100644 --- a/src/protocol/swg/objectControllerObjects/DataTransform.java +++ b/src/protocol/swg/objectControllerObjects/DataTransform.java @@ -21,15 +21,14 @@ ******************************************************************************/ package protocol.swg.objectControllerObjects; +import java.nio.BufferUnderflowException; import java.nio.ByteOrder; - import java.lang.Math; import org.apache.mina.core.buffer.IoBuffer; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; - import protocol.swg.ObjControllerMessage; public class DataTransform extends ObjControllerObject { @@ -93,21 +92,23 @@ public class DataTransform extends ObjControllerObject { } public void deserialize(IoBuffer buffer) { - objectId = buffer.getLong(); - buffer.getInt(); - - movementStamp = buffer.getInt(); - movementIndex = buffer.getInt(); - - xOrientation = buffer.getFloat(); - yOrientation = buffer.getFloat(); - zOrientation = buffer.getFloat(); - wOrientation = buffer.getFloat(); - - xPosition = buffer.getFloat(); - yPosition = buffer.getFloat(); - zPosition = buffer.getFloat(); - speed = buffer.getFloat(); + try{ + objectId = buffer.getLong(); + buffer.getInt(); + + movementStamp = buffer.getInt(); + movementIndex = buffer.getInt(); + + xOrientation = buffer.getFloat(); + yOrientation = buffer.getFloat(); + zOrientation = buffer.getFloat(); + wOrientation = buffer.getFloat(); + + xPosition = buffer.getFloat(); + yPosition = buffer.getFloat(); + zPosition = buffer.getFloat(); + speed = buffer.getFloat(); + } catch (BufferUnderflowException ex){System.err.println("BufferUnderflowException during Datatransform deserialization");} } public IoBuffer serialize() { diff --git a/src/protocol/swg/objectControllerObjects/ObjController_0250.java b/src/protocol/swg/objectControllerObjects/ObjController_0250.java new file mode 100644 index 00000000..35a7a1e1 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/ObjController_0250.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; +import resources.datatables.HitType; + +@SuppressWarnings("unused") +public class ObjController_0250 extends ObjControllerObject{ + + private long creatureId; + + public ObjController_0250(long creatureId) { + this.creatureId = creatureId; + } + + public void deserialize(IoBuffer data) { + + } + + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); + result.putInt((int)(System.currentTimeMillis()/1000)); + int packetSize = result.position(); + result = IoBuffer.allocate(packetSize).put(result.array(), 0, packetSize); + + return result.flip(); + + } + +} diff --git a/src/protocol/swg/objectControllerObjects/QuestTaskTimerMessage.java b/src/protocol/swg/objectControllerObjects/QuestTaskTimerMessage.java new file mode 100644 index 00000000..1d4b2a8c --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/QuestTaskTimerMessage.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; + +@SuppressWarnings("unused") +public class QuestTaskTimerMessage extends ObjControllerObject { + + private long objectId; + private String questName; + + public QuestTaskTimerMessage(long objectId, String questName) { + this.objectId = objectId; + this.questName = questName; + } + + @Override + public void deserialize(IoBuffer data) { + + } + + @Override + public IoBuffer serialize() { + + IoBuffer buffer = IoBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN); + buffer.setAutoExpand(true); + buffer.putInt(ObjControllerMessage.QUEST_TASK_TIMER_MESSAGE); + buffer.putLong(objectId); + buffer.putInt(0); + buffer.put(getAsciiString("quest/ep3_trando_hssissk_zssik_10")); + buffer.putInt(1); + buffer.put(getUnicodeString("quest/groundquests:destroy_counter")); + buffer.putInt(0); + buffer.putInt(1); + + int size = buffer.position(); + buffer = IoBuffer.allocate(size).put(buffer.array(), 0, size); + + return buffer.flip(); + } + +} diff --git a/src/resources/common/Forager.java b/src/resources/common/Forager.java index 48a26ca5..5f693253 100644 --- a/src/resources/common/Forager.java +++ b/src/resources/common/Forager.java @@ -180,7 +180,7 @@ public class Forager { } // chosenObject = 5; // To test TMs - if(forager.getClient().isGM()) // Always yield a TM for testing + if(!(NGECore.getInstance().adminService.getAccessLevelFromDB(forager.getClient().getAccountId()) == null)) // Always yield a TM for testing chosenObject = 5; //forager.sendSystemMessage("chosenObject " + chosenObject,(byte) 0); diff --git a/src/resources/objectives/BountyMissionObjective.java b/src/resources/objectives/BountyMissionObjective.java index 5ed1b0c0..688e1397 100644 --- a/src/resources/objectives/BountyMissionObjective.java +++ b/src/resources/objectives/BountyMissionObjective.java @@ -304,12 +304,12 @@ public class BountyMissionObjective extends MissionObjective { WaypointObject missionWp = mission.getWaypoint(); - if (missionWp == null || missionWp.getPlanetCRC() != CRC.StringtoCRC(target.getPlanet().name)) { + if (missionWp == null || missionWp.getPlanetCrc() != CRC.StringtoCRC(target.getPlanet().name)) { WaypointObject waypoint = (WaypointObject) getMissionObject().getWaypoint(); waypoint.setActive(true); waypoint.setColor(WaypointObject.ORANGE); waypoint.setName(getMissionObject().getTargetName()); - waypoint.setPlanetCRC(CRC.StringtoCRC(target.getPlanet().getName())); + waypoint.setPlanetCrc(CRC.StringtoCRC(target.getPlanet().getName())); waypoint.setStringAttribute("", ""); waypoint.setPosition(target.getWorldPosition()); mission.setWaypoint(waypoint); @@ -352,12 +352,12 @@ public class BountyMissionObjective extends MissionObjective { WaypointObject missionWp = mission.getWaypoint(); - if (missionWp == null || missionWp.getPlanetCRC() != CRC.StringtoCRC(target.getPlanet().name)) { + if (missionWp == null || missionWp.getPlanetCrc() != CRC.StringtoCRC(target.getPlanet().name)) { WaypointObject waypoint = (WaypointObject) getMissionObject().getWaypoint(); waypoint.setActive(true); waypoint.setColor(WaypointObject.ORANGE); waypoint.setName(getMissionObject().getTargetName()); - waypoint.setPlanetCRC(CRC.StringtoCRC(target.getPlanet().getName())); + waypoint.setPlanetCrc(CRC.StringtoCRC(target.getPlanet().getName())); waypoint.setStringAttribute("", ""); waypoint.setPosition(target.getWorldPosition()); mission.setWaypoint(waypoint); @@ -388,7 +388,7 @@ public class BountyMissionObjective extends MissionObjective { waypoint.setActive(true); waypoint.setColor(WaypointObject.ORANGE); waypoint.setName(getMissionObject().getTargetName()); - waypoint.setPlanetCRC(CRC.StringtoCRC(target.getPlanet().getName())); + waypoint.setPlanetCrc(CRC.StringtoCRC(target.getPlanet().getName())); waypoint.setStringAttribute("", ""); getMissionObject().setWaypoint(waypoint); diff --git a/src/resources/objectives/DeliveryMissionObjective.java b/src/resources/objectives/DeliveryMissionObjective.java index c4eef253..a4645c0f 100644 --- a/src/resources/objectives/DeliveryMissionObjective.java +++ b/src/resources/objectives/DeliveryMissionObjective.java @@ -54,7 +54,7 @@ public class DeliveryMissionObjective extends MissionObjective { if (getObjectivePhase() == 0) { WaypointObject waypoint = getMissionObject().getWaypoint(); - waypoint.setPlanetCRC(CRC.StringtoCRC(player.getPlanet().name)); + waypoint.setPlanetCrc(CRC.StringtoCRC(player.getPlanet().name)); waypoint.setPosition(parent.getStartLocation().getLocation()); waypoint.setName("@" + parent.getTitle().getStfFilename() + ":" + "m" + parent.getMissionId() + "t"); waypoint.setColor(WaypointObject.ORANGE); @@ -63,7 +63,7 @@ public class DeliveryMissionObjective extends MissionObjective { } else if (getObjectivePhase() == 1) { WaypointObject waypoint = getMissionObject().getWaypoint(); - waypoint.setPlanetCRC(CRC.StringtoCRC(player.getPlanet().name)); + waypoint.setPlanetCrc(CRC.StringtoCRC(player.getPlanet().name)); waypoint.setPosition(parent.getDestinationLocation().getLocation()); waypoint.setName("@" + parent.getTitle().getStfFilename() + ":" + "m" + parent.getMissionId() + "t"); waypoint.setColor(WaypointObject.ORANGE); @@ -103,7 +103,7 @@ public class DeliveryMissionObjective extends MissionObjective { waypoint.setName("@" + parent.getTitle().getStfFilename() + ":" + "m" + parent.getMissionId() + "t"); waypoint.setColor(WaypointObject.ORANGE); waypoint.setActive(true); - waypoint.setPlanetCRC(CRC.StringtoCRC(player.getPlanet().name)); + waypoint.setPlanetCrc(CRC.StringtoCRC(player.getPlanet().name)); getMissionObject().setTargetName("Dropoff Location"); getMissionObject().setWaypoint(waypoint); break; @@ -113,7 +113,7 @@ public class DeliveryMissionObjective extends MissionObjective { returnWp.setName("@" + parent.getTitle().getStfFilename() + ":" + "m" + parent.getMissionId() + "t"); returnWp.setColor(WaypointObject.ORANGE); returnWp.setActive(true); - returnWp.setPlanetCRC(CRC.StringtoCRC(player.getPlanet().name)); + returnWp.setPlanetCrc(CRC.StringtoCRC(player.getPlanet().name)); getMissionObject().setTargetName("Return"); getMissionObject().setWaypoint(returnWp); break; diff --git a/src/resources/objects/building/BuildingObject.java b/src/resources/objects/building/BuildingObject.java index fa44577f..cc61cb83 100644 --- a/src/resources/objects/building/BuildingObject.java +++ b/src/resources/objects/building/BuildingObject.java @@ -403,7 +403,7 @@ public class BuildingObject extends TangibleObject implements IPersistent, Seria } public boolean canEnter(SWGObject object) { - return (getPrivacy() == PRIVATE && (entryList.contains(object.getObjectID()) || adminList.contains(object.getObjectID()))) || !banList.contains(object.getObjectID()) || object.getClient().isGM(); + return (getPrivacy() == PRIVATE && (entryList.contains(object.getObjectID()) || adminList.contains(object.getObjectID()))) || !banList.contains(object.getObjectID()) || !(NGECore.getInstance().adminService.getAccessLevelFromDB(client.getAccountId()) == null); } public void updateCellPermissions(SWGObject obj) { diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index 93c58e5e..b069864e 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -307,7 +307,7 @@ public class CreatureMessageBuilder extends TangibleMessageBuilder { SWGObject obj = NGECore.getInstance().objectService.getObject(objId); if(obj == null) { - System.err.println("Cant find obj for obj id in equip list!!!"); + System.err.println("Cant find obj for obj id in equip list!!! (Normal Message for AI wipes)"); continue; } @@ -427,7 +427,7 @@ public class CreatureMessageBuilder extends TangibleMessageBuilder { SWGObject obj = NGECore.getInstance().objectService.getObject(objId); if(obj == null) { - System.err.println("Cant find obj for obj id in equip list!!!"); + System.err.println("Cant find obj for obj id in equip list!!! (Normal Message for AI wipes)"); continue; } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 1bbe384c..91dd3446 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -188,6 +188,8 @@ public class CreatureObject extends TangibleObject implements Serializable { private transient CreatureObject calledPet; private byte locomotion = 0; + private int GCWFatigue = 0; + private boolean isConstructing = false; public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { super(objectID, planet, position, orientation, Template); @@ -545,6 +547,9 @@ public class CreatureObject extends TangibleObject implements Serializable { if (companion != null) { companion.setFaction(faction); } + + if (this.getCalledPet()!=null) + this.getCalledPet().setFaction(faction); } public void setFactionStatus(int factionStatus) { @@ -555,6 +560,8 @@ public class CreatureObject extends TangibleObject implements Serializable { if (companion != null) { companion.setFactionStatus(factionStatus); } + if (this.getCalledPet()!=null) + this.getCalledPet().setFactionStatus(factionStatus); } public float getHeight() { @@ -1148,7 +1155,7 @@ public class CreatureObject extends TangibleObject implements Serializable { } //destination.getSession().write(messageBuilder.buildBaseline8()); //destination.getSession().write(messageBuilder.buildBaseline9()); - + if(destination != getClient()) { UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID(), NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this), getFaction()); destination.getSession().write(upvpm.serialize()); @@ -1887,4 +1894,34 @@ public class CreatureObject extends TangibleObject implements Serializable { public void setCalledPet(CreatureObject calledPet) { this.calledPet = calledPet; } + + public int getGCWFatigue() { + return GCWFatigue; + } + + public void setGCWFatigue(int gCWFatigue) { + GCWFatigue = gCWFatigue; + } + + public boolean isTrader(){ + if (isPlayer()){ + PlayerObject player = (PlayerObject) this.getSlottedObject("ghost"); + String profession = player.getProfession(); + if (profession.equals("trader_0a") || + profession.equals("trader_0b") || + profession.equals("trader_0c") || + profession.equals("trader_0d")){ + return true; + } + } + return false; + } + + public boolean isConstructing() { + return isConstructing; + } + + public void setConstructing(boolean isConstructing) { + this.isConstructing = isConstructing; + } } diff --git a/src/resources/objects/installation/InstallationMessageBuilder.java b/src/resources/objects/installation/InstallationMessageBuilder.java index d2b1f80c..0ec055fa 100644 --- a/src/resources/objects/installation/InstallationMessageBuilder.java +++ b/src/resources/objects/installation/InstallationMessageBuilder.java @@ -25,7 +25,6 @@ import java.nio.ByteOrder; import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; - import engine.resources.objects.Builder; import resources.objects.tangible.TangibleMessageBuilder; @@ -215,6 +214,27 @@ public class InstallationMessageBuilder extends TangibleMessageBuilder{ // 0010: 4E 49 07 12 00 00 00 02 00 09 00 00 00 00 00 05 NI.............. // 0020: 00 8A D3 79 16 00 00 0F 00 ...y..... + public IoBuffer buildCustomNameDelta(InstallationObject installation, String customName) { + IoBuffer buffer = IoBuffer.allocate(10).order(ByteOrder.LITTLE_ENDIAN); + buffer.setAutoExpand(true); + int sizeP = 8; + sizeP += 2*customName.length(); + buffer.putShort((short)5); + buffer.putInt(0x12862153); + buffer.putLong(installation.getObjectID()); + buffer.putInt(0x54414E4F); + buffer.put((byte)3); + buffer.putInt(sizeP); + buffer.putShort((short)1); + buffer.putShort((short)2); + buffer.put(getUnicodeString(customName)); + int size = buffer.position(); + buffer.flip(); + tools.CharonPacketUtils.printAnalysis(IoBuffer.allocate(size).put(buffer.array(), 0, size).flip()); + return IoBuffer.allocate(size).put(buffer.array(), 0, size).flip(); + } + + @Override public void buildBaseline3(Map baselineBuilders, Map deltaBuilders) { super.buildBaseline3(deltaBuilders, deltaBuilders); diff --git a/src/resources/objects/installation/InstallationObject.java b/src/resources/objects/installation/InstallationObject.java index b9cc98d6..46cb6a24 100644 --- a/src/resources/objects/installation/InstallationObject.java +++ b/src/resources/objects/installation/InstallationObject.java @@ -24,16 +24,21 @@ package resources.objects.installation; import java.io.Serializable; import java.util.Vector; -import com.sleepycat.persist.model.Entity; +import org.apache.mina.core.buffer.IoBuffer; +import main.NGECore; +import protocol.swg.UpdatePVPStatusMessage; import engine.clients.Client; +import engine.resources.common.CRC; +import engine.resources.objects.Baseline; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; +import resources.datatables.Options; import resources.objects.ObjectMessageBuilder; +import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; -@Entity(version=0) public class InstallationObject extends TangibleObject implements Serializable { private static final long serialVersionUID = 1L; @@ -44,20 +49,94 @@ public class InstallationObject extends TangibleObject implements Serializable { messageBuilder = new InstallationMessageBuilder(this); } +// @Override +// public void sendBaselines(Client destination) { +// +// if(destination == null || destination.getSession() == null) { +// //System.out.println("NULL session"); +// return; +// } +// +// destination.getSession().write(messageBuilder.buildBaseline3(this)); +// //destination.getSession().write(messageBuilder.buildBaseline6(this)); +// +// if(destination != getClient()) { +// UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID(), NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this), getFaction()); +// destination.getSession().write(upvpm.serialize()); +// } +// } + + public Baseline getBaseline3() { + Baseline baseline = super.getBaseline3(); + baseline.put("activeFlag", false); + baseline.put("PowerReserves", 0); + baseline.put("PowerCost", 0); + return baseline; + } + + @Override public void sendBaselines(Client destination) { - + if (destination != null && destination.getSession() != null) { + + // Factional peculiarities + Baseline baseLine3 = getBaseline(3); + if (destination.getParent() instanceof CreatureObject){ + if (((CreatureObject) destination.getParent()).isPlayer() && ((CreatureObject) destination.getParent()).getFaction()!=this.getFaction()){ + int optionsBitMask = getOptionsBitmask(); + if (getOption(Options.QUEST)) + optionsBitMask = optionsBitMask & ~Options.QUEST; + if (!getOption(Options.ATTACKABLE)) + optionsBitMask = optionsBitMask | Options.ATTACKABLE; + + baseLine3.set("optionsBitmask", optionsBitMask); + } + } + + //destination.getSession().write(getBaseline(3).getBaseline()); + destination.getSession().write(baseLine3.getBaseline()); + destination.getSession().write(getBaseline(6).getBaseline()); + + Client parent = ((getGrandparent() == null) ? null : getGrandparent().getClient()); + + if (parent != null && destination == parent) { + destination.getSession().write(getBaseline(8).getBaseline()); + destination.getSession().write(getBaseline(9).getBaseline()); + } + + if (destination.getParent() != this) { + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); + upvpm.setFaction(CRC.StringtoCRC(getFaction())); +// if (this.getTemplate().contains("turret")){ +// System.out.println("TURRET RESULT " + NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this)); +// } + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this)); + destination.getSession().write(upvpm.serialize()); + } + } } + @Override + public void notifyClients(IoBuffer buffer, boolean notifySelf) { + notifyObservers(buffer, false); + } + + @Override + public ObjectMessageBuilder getMessageBuilder() { + synchronized(objectMutex) { + if (messageBuilder == null) { + messageBuilder = new InstallationMessageBuilder(this); + } + return messageBuilder; + } + } + + @Override public void initAfterDBLoad() { super.init(); messageBuilder = new InstallationMessageBuilder(this); defendersList = new Vector(); } - - public ObjectMessageBuilder getMessageBuilder() { - return messageBuilder; - } - + } \ No newline at end of file diff --git a/src/resources/objects/resource/GalacticResource.java b/src/resources/objects/resource/GalacticResource.java index b3c6e3e8..33b81bed 100644 --- a/src/resources/objects/resource/GalacticResource.java +++ b/src/resources/objects/resource/GalacticResource.java @@ -441,7 +441,7 @@ public class GalacticResource extends SWGObject implements Serializable { if (lastSurveyWaypoint == null) { surveyWaypoint = (WaypointObject) NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", crafter.getPlanet(), smuMsg.getHighestX(), 0, smuMsg.getHighestZ()); surveyWaypoint.setName("Survey location"); - surveyWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(crafter.getPlanet().getName())); + surveyWaypoint.setPlanetCrc(engine.resources.common.CRC.StringtoCRC(crafter.getPlanet().getName())); surveyWaypoint.setPosition(new Point3D(smuMsg.getHighestX(), 0, smuMsg.getHighestZ())); player.waypointAdd(surveyWaypoint); surveyWaypoint.setPosition(new Point3D(smuMsg.getHighestX(), 0, smuMsg.getHighestZ())); @@ -450,7 +450,7 @@ public class GalacticResource extends SWGObject implements Serializable { surveyWaypoint.setStringAttribute("", ""); player.waypointAdd(surveyWaypoint); surveyWaypoint.setName("Survey location"); - surveyWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(crafter.getPlanet().getName())); + surveyWaypoint.setPlanetCrc(engine.resources.common.CRC.StringtoCRC(crafter.getPlanet().getName())); player.setLastSurveyWaypoint(surveyWaypoint); } else { surveyWaypoint = lastSurveyWaypoint; diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 328a23cb..0a5c86e0 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -24,6 +24,7 @@ package resources.objects.tangible; import java.io.ByteArrayOutputStream; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -241,6 +242,8 @@ public class TangibleObject extends SWGObject implements Serializable { public void setOptionsBitmask(int optionsBitmask) { notifyClients(getBaseline(3).set("optionsBitmask", optionsBitmask), true); + // This needs to be refactored to be sent to clients with different values depending on their faction + // A quest object for one faction, can't be quest object for opposing faction } public void setOptions(int options, boolean add) { @@ -322,18 +325,30 @@ public class TangibleObject extends SWGObject implements Serializable { // All objects can be in combat (terminal mission flag bases, tutorial target box) public List getDefendersList() { - synchronized(objectMutex) { + synchronized(defendersList) { return defendersList; } } + public List getDefendersListClone() { + synchronized(objectMutex) { + List returnList = new Vector(); + Collections.copy(returnList, defendersList); + return returnList; + } + } + public void addDefender(TangibleObject defender) { - if (((CreatureObject)this).getOwnerId()>0){ - if (((CreatureObject)this).getOwnerId()==defender.getObjectID()){ - return; // fix for now until determined where the tamer is added from + if (this instanceof CreatureObject){ + if (((CreatureObject)this).getOwnerId()>0){ + if (((CreatureObject)this).getOwnerId()==defender.getObjectID()){ + return; // fix for now until determined where the tamer is added from + } } } - defendersList.add(defender); + synchronized(defendersList) { + defendersList.add(defender); + } if (!isInCombat()) { setInCombat(true); @@ -341,13 +356,15 @@ public class TangibleObject extends SWGObject implements Serializable { } public void removeDefender(TangibleObject defender) { - defendersList.remove(defender); - - if (defendersList.isEmpty() && isInCombat()) { - setInCombat(false); + synchronized(defendersList) { + defendersList.remove(defender); + + if (defendersList.isEmpty() && isInCombat()) { + setInCombat(false); + } } } - + public int getPvpBitmask() { synchronized(objectMutex) { return pvpBitmask; @@ -387,10 +404,10 @@ public class TangibleObject extends SWGObject implements Serializable { if (observer.getParent() != null) { observer.getSession().write(new UpdatePVPStatusMessage(this.getObjectID(), NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) observer.getParent(), this), getFaction()).serialize()); - if(getClient() != null) - getClient().getSession().write(new UpdatePVPStatusMessage(observer.getParent().getObjectID(), NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) this, (CreatureObject) observer.getParent()), getFaction()).serialize()); + if(getClient() != null){ + getClient().getSession().write(new UpdatePVPStatusMessage(observer.getParent().getObjectID(), NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) this, (CreatureObject) observer.getParent()), getFaction()).serialize()); + } } - } if (getClient() != null) { @@ -400,16 +417,6 @@ public class TangibleObject extends SWGObject implements Serializable { companion.updatePvpStatus(); } } - - - if (this instanceof CreatureObject){ - if (((CreatureObject)this).isPlayer()){ - // Here a specific CREO delta must be sent to update the faction info in character sheet and symbol in name - // If anyone knows which that would be, please replace it here! - sendBaselines(this.getClient()); - - } - } } public boolean isAttackableBy(CreatureObject attacker) { @@ -602,7 +609,8 @@ public class TangibleObject extends SWGObject implements Serializable { } public void notifyClients(IoBuffer buffer, boolean notifySelf) { - notifyObservers(buffer, false); + // notifyObservers(buffer, false); // ??? Ignores the notifySelf argument. Was this done purposely? Faction Status etc. can't update the client without it + notifyObservers(buffer, notifySelf); } public ObjectMessageBuilder getMessageBuilder() { @@ -615,9 +623,26 @@ public class TangibleObject extends SWGObject implements Serializable { } } + @Override public void sendBaselines(Client destination) { if (destination != null && destination.getSession() != null) { - destination.getSession().write(getBaseline(3).getBaseline()); + + // Factional peculiarities + Baseline baseLine3 = getBaseline(3); + if (destination.getParent() instanceof CreatureObject){ + if (((CreatureObject) destination.getParent()).isPlayer() && ((CreatureObject) destination.getParent()).getFaction()!=this.getFaction()){ + int optionsBitMask = getOptionsBitmask(); + if (getOption(Options.QUEST)) + optionsBitMask = optionsBitMask & ~Options.QUEST; + if (!getOption(Options.ATTACKABLE)) + optionsBitMask = optionsBitMask | Options.ATTACKABLE; + + baseLine3.set("optionsBitmask", optionsBitMask); + } + } + + //destination.getSession().write(getBaseline(3).getBaseline()); + destination.getSession().write(baseLine3.getBaseline()); destination.getSession().write(getBaseline(6).getBaseline()); Client parent = ((getGrandparent() == null) ? null : getGrandparent().getClient()); @@ -630,12 +655,18 @@ public class TangibleObject extends SWGObject implements Serializable { if (destination.getParent() != this) { UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); upvpm.setFaction(CRC.StringtoCRC(getFaction())); +// if (this.getTemplate().contains("barricade")){ +// System.out.println("BARTANO RESULT " + NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this)); +// } + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), this)); destination.getSession().write(upvpm.serialize()); } } } + + public void sendListDelta(byte viewType, short updateType, IoBuffer buffer) { switch (viewType) { case 3: diff --git a/src/resources/objects/waypoint/WaypointObject.java b/src/resources/objects/waypoint/WaypointObject.java index fa04db07..8dd5337d 100644 --- a/src/resources/objects/waypoint/WaypointObject.java +++ b/src/resources/objects/waypoint/WaypointObject.java @@ -22,147 +22,162 @@ package resources.objects.waypoint; import java.io.Serializable; -import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; -import org.apache.mina.core.buffer.SimpleBufferAllocator; -import resources.objects.intangible.IntangibleObject; -import engine.clients.Client; import engine.resources.common.StringUtilities; +import engine.resources.common.UString; +import engine.resources.objects.Baseline; import engine.resources.objects.IDelta; import engine.resources.objects.SWGObject; +import resources.objects.intangible.IntangibleObject; +import engine.clients.Client; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -public class WaypointObject extends IntangibleObject implements Serializable, IDelta { +public class WaypointObject extends IntangibleObject implements IDelta, Serializable { private static final long serialVersionUID = 1L; - private int cellId; // ??? - private long locationNetworkId; - private int planetCRC; - private String name = ""; - private byte color; - private boolean isActive; - private transient static SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); + public static final byte BLUE = 1, GREEN = 2, ORANGE = 3, YELLOW = 4, PURPLE = 5, WHITE = 6, MULTICOLOR = 7; - public static final byte BLUE = 1; - public static final byte GREEN = 2; - public static final byte ORANGE = 3; - public static final byte YELLOW = 4; - public static final byte PURPLE = 5; - public static final byte WHITE = 6; - public static final byte MULTICOLOR = 7; // JTL waypoint - - public WaypointObject() { } - public WaypointObject(long objectID, Planet planet, Point3D position) { - super(objectID, planet, position, new Quaternion(0, 0, 0, 1), "object/waypoint/shared_waypoint.iff"); + super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(0, 0, 0, 1), "object/waypoint/shared_waypoint.iff"); + } + + public WaypointObject() { + super(); } - @Override public void initAfterDBLoad() { super.init(); } - public synchronized int getCellId() { - return cellId; - } - - - public synchronized void setCellId(int cellId) { - this.cellId = cellId; - } - - - public synchronized long getLocationNetworkId() { - return locationNetworkId; - } - - - public synchronized void setLocationNetworkId(long locationNetworkId) { - this.locationNetworkId = locationNetworkId; - } - - - public synchronized int getPlanetCRC() { - return planetCRC; - } - - - public synchronized void setPlanetCRC(int planetCRC) { - this.planetCRC = planetCRC; - } - - - public synchronized String getName() { - return name; - } - - - public synchronized void setName(String name) { - this.name = name; - } - - - public synchronized byte getColor() { - return color; - } - - - public synchronized void setColor(byte color) { - this.color = color; - } - - - public synchronized boolean isActive() { - return isActive; - } - - - public void setActive(boolean isActive) { - this.isActive = isActive; - } - - @Override - public void sendBaselines(Client client) { - // TODO Auto-generated method stub - - } - - @Override - public byte[] getBytes() { - IoBuffer buffer = bufferPool.allocate(42 + name.length() * 2, false).order(ByteOrder.LITTLE_ENDIAN); - - buffer.putInt(getCellId()); - - buffer.putFloat(getPosition().x); - buffer.putFloat(getPosition().y); - buffer.putFloat(getPosition().z); - - buffer.putLong(0); // networklocationId - buffer.putInt(getPlanetCRC()); - - buffer.put(StringUtilities.getUnicodeString(getName())); - buffer.putLong(getObjectID()); - - buffer.put((byte) getColor()); - - if (isActive()) - buffer.put((byte) 1); - else - buffer.put((byte) 0); - - return buffer.flip().array(); - - } - - @Override - public void init(SWGObject arg0) { - // TODO Auto-generated method stub + public void init(SWGObject object) { } + public Baseline getOtherVariables() { + Baseline baseline = super.getOtherVariables(); + return baseline; + } + + public Baseline getBaseline3() { + Baseline baseline = super.getBaseline3(); + baseline.put("cellNumber", 0); + baseline.put("position", new Point3D(0, 0, 0)); + baseline.put("targetId", (long) 0); + baseline.put("planetCrc", 0); + baseline.put("name", new UString("Waypoint")); + baseline.put("color", (byte) 1); + baseline.put("active", false); + return baseline; + } + + public Baseline getBaseline6() { + Baseline baseline = super.getBaseline6(); + return baseline; + } + + @Override + public Baseline getBaseline8() { + Baseline baseline = super.getBaseline8(); + return baseline; + } + + @Override + public Baseline getBaseline9() { + Baseline baseline = super.getBaseline9(); + return baseline; + } + + public int getCellNumber() { + return (int) getBaseline(3).get("cellNumber"); + } + + public void setCellNumber(int cellNumber) { + getBaseline(3).set("cellNumber", cellNumber); + } + + public void setPosition(Point3D position) { + getBaseline(3).set("position", position); + } + + public long getTargetId() { + return (long) getBaseline(3).get("targetId"); + } + + public void setTargetId(long targetId) { + getBaseline(3).set("targetId", targetId); + } + + public int getPlanetCrc() { + return (int) getBaseline(3).get("planetCrc"); + } + + public void setPlanetCrc(int planetCrc) { + getBaseline(3).set("planetCrc", planetCrc); + } + + public String getName() { + return ((UString) getBaseline(3).get("name")).get(); + } + + public void setName(String name) { + getBaseline(3).set("name", new UString(name)); + } + + public byte getColor() { + return (byte) getBaseline(3).get("color"); + } + + public void setColor(byte color) { + getBaseline(3).set("color", color); + } + + public boolean isActive() { + return (boolean) getBaseline(3).get("active"); + } + + public void setActive(boolean active) { + getBaseline(3).set("active", active); + } + + public void toggleActive() { + setActive(!isActive()); + } + + @Override + public void sendBaselines(Client destination) { + + } + + public byte[] getBytes() { + synchronized(objectMutex) { + IoBuffer buffer = Baseline.createBuffer(38 + StringUtilities.getUnicodeString(getName()).length); + buffer.putInt(getCellNumber()); + buffer.put(Baseline.toBytes(getBaseline(3).get("position"))); + buffer.putLong(getTargetId()); + buffer.putInt(getPlanetCrc()); + buffer.put(StringUtilities.getUnicodeString(getName())); + buffer.putLong(getObjectID()); + buffer.put(getColor()); + buffer.put(Baseline.getBoolean(isActive())); + return buffer.flip().array(); + } + } + + @Deprecated public int getCellId() { return getCellNumber(); } + + @Deprecated public void setCellId(int cellId) { setCellNumber(cellId); } + + @Deprecated public long getLocationNetworkId() { return getTargetId(); } + + @Deprecated public void setLocationNetworkId(long locationNetworkId) { setTargetId(locationNetworkId); } + + @Deprecated public int getPlanetCRC() { return getPlanetCrc(); } + + @Deprecated public void setPlanetCRC(int planetCRC) { setPlanetCrc(planetCRC); } + } diff --git a/src/services/AdminService.java b/src/services/AdminService.java new file mode 100644 index 00000000..3763a874 --- /dev/null +++ b/src/services/AdminService.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; +import java.sql.PreparedStatement; + +import main.NGECore; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class AdminService implements INetworkDispatch { + + private NGECore core; + + public AdminService(NGECore core) { + this.core = core; + + } + + public String getAccessLevelFromDB(long id) { + String accessLevel = null; + PreparedStatement preparedStatement; + + try { + preparedStatement = NGECore.getInstance().getDatabase1().preparedStatement("SELECT * FROM accounts WHERE id=" + id + ""); + ResultSet resultSet = preparedStatement.executeQuery(); + if(resultSet.next()) + accessLevel = resultSet.getString("accessLevel"); + } catch (SQLException e) { + e.printStackTrace(); + } + + return accessLevel; + } + + @Override + public void insertOpcodes(Map arg0, Map arg1) { + + } + + @Override + public void shutdown() { + + } + +} diff --git a/src/services/BuffService.java b/src/services/BuffService.java index 70a24957..c68b1432 100644 --- a/src/services/BuffService.java +++ b/src/services/BuffService.java @@ -22,8 +22,10 @@ package services; import java.util.Map; +import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -34,6 +36,7 @@ import org.python.core.PyObject; import resources.buffs.Buff; import resources.buffs.DamageOverTime; import resources.common.FileUtilities; +import resources.datatables.Posture; import resources.objects.creature.CreatureObject; import resources.objects.group.GroupObject; import resources.objects.player.PlayerObject; @@ -51,6 +54,22 @@ public class BuffService implements INetworkDispatch { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private ConcurrentHashMap buffMap = new ConcurrentHashMap(); + private static Map bannerBuffMapping = new ConcurrentHashMap(); + static{ + bannerBuffMapping.put("trader_0a", "banner_buff_trader"); + bannerBuffMapping.put("trader_0b", "banner_buff_trader"); + bannerBuffMapping.put("trader_0c", "banner_buff_trader"); + bannerBuffMapping.put("trader_0d", "banner_buff_trader"); + bannerBuffMapping.put("entertainer_1a", "banner_buff_entertainer"); + bannerBuffMapping.put("medic_1a", "banner_buff_medic"); + bannerBuffMapping.put("officer_1a", "banner_buff_officer"); + bannerBuffMapping.put("bounty_hunter_1a", "banner_buff_bounty_hunter"); + bannerBuffMapping.put("smuggler_1a", "banner_buff_smuggler"); + bannerBuffMapping.put("commando_1a", "banner_buff_commando"); + bannerBuffMapping.put("spy_1a", "banner_buff_spy"); + bannerBuffMapping.put("force_sensitive_1a", "banner_buff_force_sensitive"); + } + public BuffService(NGECore core) { this.core = core; core.commandService.registerCommand("removeBuff"); @@ -102,6 +121,10 @@ public class BuffService implements INetworkDispatch { } else { if (! hasBuff(target,buffName)) // QA, prevent infinite "refreshing" of buff by repeated use doAddBuff(target, buffName, buffer); + else { + if (buff.getMaxStacks()>1) + doAddBuff(target, buffName, buffer); + } return true; } } @@ -182,6 +205,12 @@ public class BuffService implements INetworkDispatch { if(buff.getEffect4Name().length() > 0) core.skillModService.addSkillMod(target, buff.getEffect4Name(), (int) buff.getEffect4Value()); if(buff.getEffect5Name().length() > 0) core.skillModService.addSkillMod(target, buff.getEffect5Name(), (int) buff.getEffect5Value()); // } + + if (buffName.equals("gcw_fatigue")){ + if (FileUtilities.doesFileExist("scripts/buffs/" + buffName + ".py")) { + core.scriptService.callScript("scripts/buffs/", buffName, "add", core, buffer, buff); + } + } target.addBuff(buff); @@ -414,6 +443,56 @@ public class BuffService implements INetworkDispatch { } + public void applyGCWBuff(String buffName, String factionName, SWGObject center) { + Vector inRangeObjects = core.simulationService.getAllNearSameFactionCreatures(10, center.getWorldPosition(), center.getPlanet(), factionName); + for(SWGObject obj : inRangeObjects) { + if(!(obj instanceof CreatureObject)) + continue; + if(obj instanceof CreatureObject && (((CreatureObject) obj).getPosture() == Posture.Dead)) + continue; + CreatureObject buffed = (CreatureObject) obj; + if (! buffed.hasBuff(buffName)) + addBuffToCreature(buffed, buffName, buffed); + } + } + + public void initiateBannerBuffProcess(CreatureObject buffer, SWGObject banner){ + + String factionName = buffer.getFaction(); + String professionName = buffer.getPlayerObject().getProfession(); + String buffName = bannerBuffMapping.get(professionName); + applyGCWBuff(buffName, factionName, banner); + + final Future[] fut = {null}; + fut[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().objectService.getObject(banner.getObjectID())==null){ + Thread.yield(); + fut[0].cancel(false); + } + + applyGCWBuff(buffName, factionName, banner); + + if (! buffer.isInQuadtree()){ + NGECore.getInstance().objectService.destroyObject(banner.getObjectID()); + Thread.yield(); + fut[0].cancel(false); + } + + if (buffer.getWorldPosition().getDistance2D(banner.getWorldPosition())>1000 || buffer.getPlanetId()!=banner.getPlanetId()){ + NGECore.getInstance().objectService.destroyObject(banner.getObjectID()); + Thread.yield(); + fut[0].cancel(false); + } + + } catch (Exception e) { + System.err.println("Exception in GCW Banner thread " + e.getMessage()); + } + } + }, 0, 2, TimeUnit.SECONDS); + } + private void loadBuffs() { try { DatatableVisitor visitor = ClientFileManager.loadFile("datatables/buff/buff.iff", DatatableVisitor.class); diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index 873b3fa7..a1fff102 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -39,6 +39,7 @@ import engine.clientdata.visitors.DatatableVisitor; import engine.clientdata.visitors.ProfessionTemplateVisitor; import engine.clients.Client; import engine.resources.common.CRC; +import engine.resources.config.Config; import engine.resources.container.CreatureContainerPermissions; import engine.resources.container.CreaturePermissions; import engine.resources.container.Traverser; @@ -265,7 +266,15 @@ public class CharacterService implements INetworkDispatch { object.setCustomName(clientCreateCharacter.getName()); object.setHeight(clientCreateCharacter.getScale()); object.setPersistent(true); - object.setPosition(SpawnPoint.getRandomPosition(new Point3D(3528, 0, -4804), (float) 0.5, 3, core.terrainService.getPlanetByName("tatooine").getID())); + + Config options = NGECore.getInstance().getOptions(); + + if (options != null && options.getInt("DO.ISOLATION.TESTS") > 0){ + object.setPosition(SpawnPoint.getRandomPosition(new Point3D(0, 0, 0), (float) 0.5, 3, core.terrainService.getPlanetByName("tatooine").getID())); + } else { + object.setPosition(SpawnPoint.getRandomPosition(new Point3D(3528, 0, -4804), (float) 0.5, 3, core.terrainService.getPlanetByName("tatooine").getID())); + } + object.setCashCredits(100); object.setBankCredits(1000); object.setIncapTimer(10); @@ -357,7 +366,7 @@ public class CharacterService implements INetworkDispatch { System.out.println("Saving character with name: " + object.getCustomName()); core.getSWGObjectODB().put(object.getObjectID(), object); - PreparedStatement ps = databaseConnection.preparedStatement("INSERT INTO characters (id, \"firstName\", \"lastName\", \"accountId\", \"galaxyId\", \"statusId\", appearance, gmflag) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + PreparedStatement ps = databaseConnection.preparedStatement("INSERT INTO characters (id, \"firstName\", \"lastName\", \"accountId\", \"galaxyId\", \"statusId\", appearance) VALUES (?, ?, ?, ?, ?, ?, ?)"); ps.setLong(1, object.getObjectID()); ps.setString(2, clientCreateCharacter.getFirstName()); ps.setString(3, clientCreateCharacter.getLastName()); @@ -365,7 +374,6 @@ public class CharacterService implements INetworkDispatch { ps.setInt(5, galaxyId); ps.setInt(6, 1); ps.setInt(7, CRC.StringtoCRC(raceTemplate)); - ps.setBoolean(8, false); ps.executeUpdate(); ps.close(); CreateCharacterSuccess success = new CreateCharacterSuccess(object.getObjectID()); diff --git a/src/services/ConnectionService.java b/src/services/ConnectionService.java index 4e8ce362..246501fd 100644 --- a/src/services/ConnectionService.java +++ b/src/services/ConnectionService.java @@ -137,7 +137,6 @@ public class ConnectionService implements INetworkDispatch { if (resultSet.next()) { client.setAccountId(resultSet.getLong("accountId")); client.setSessionKey(clientIdMsg.getSessionKey()); - client.setGM(core.loginService.checkForGmPermission((int) resultSet.getLong("accountId"))); AccountFeatureBits accountFeatureBits = new AccountFeatureBits(); ClientPermissionsMessage clientPermissionsMessage = new ClientPermissionsMessage(maxNumberOfCharacters - core.characterService.getNumberOfCharacters((int) resultSet.getLong("accountId"))); session.write(new HeartBeatMessage().serialize()); @@ -340,7 +339,6 @@ public class ConnectionService implements INetworkDispatch { } ghost.toggleFlag(PlayerFlags.LD); - object.setPerformanceListenee(null); object.setPerformanceWatchee(null); object.setAttachment("disconnectTask", null); diff --git a/src/services/LoginService.java b/src/services/LoginService.java index 3133269f..437970d5 100644 --- a/src/services/LoginService.java +++ b/src/services/LoginService.java @@ -140,9 +140,7 @@ public class LoginService implements INetworkDispatch{ client.setPassword(pass); client.setSessionKey(generateSessionKey()); client.setAccountId(id); - //client.setAccountEmail(email); client.setSession(session); - client.setGM(checkForGmPermission(id)); core.addClient(session, client); @@ -156,9 +154,6 @@ public class LoginService implements INetworkDispatch{ System.out.println(client.getAccountName() + " was not added to active connections map."); return; } - /*if(!checkIfAccountExistInGameDB(id)) { - createAccountForGameDB(id, user, email, encryptPass); - }*/ persistSession(client); @@ -170,6 +165,8 @@ public class LoginService implements INetworkDispatch{ CharacterCreationDisabled charCreationDisabled = new CharacterCreationDisabled(0); StationIdHasJediSlot jediSlot = new StationIdHasJediSlot(false); ServerNowEpochTime time = new ServerNowEpochTime((int) (System.currentTimeMillis() / 1000)); + //System.out.println("ServerNowEpochTime " + (int) (System.currentTimeMillis() / 1000)); + //tools.CharonPacketUtils.printAnalysis(time.serialize(), "ServerNowEpochTime"); if (client.getSession().containsAttribute("tradeSession") == true) { client.getSession().removeAttribute("tradeSession"); @@ -267,29 +264,6 @@ public class LoginService implements INetworkDispatch{ } - public boolean checkForGmPermission(int id) { - try { - if (core.getConfig().getInt("ADMIN") > 0) { - return true; - } - } catch (Exception e) { - - } - - PreparedStatement preparedStatement; - - try { - preparedStatement = databaseConnection1.preparedStatement("SELECT * FROM accounts WHERE id=" + id + ""); - ResultSet resultSet = preparedStatement.executeQuery(); - if(resultSet.next()) - return resultSet.getBoolean("gmflag"); - } catch (SQLException e) { - e.printStackTrace(); - } - - return false; - } - /** * Saves session data to DB so Zone Server can link sessions to accounts. * @param client Client that needs a session save. diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 04d1b18c..71944c7b 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -37,9 +37,11 @@ import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.concurrent.atomic.AtomicBoolean; + import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; + import protocol.swg.CharacterSheetResponseMessage; import protocol.swg.ClientIdMsg; import protocol.swg.ClientMfdStatusUpdateMessage; @@ -67,6 +69,9 @@ import resources.common.OutOfBand; import resources.common.ProsePackage; import resources.common.SpawnPoint; import resources.datatables.DisplayType; +import resources.datatables.FactionStatus; +import resources.datatables.Factions; +import resources.datatables.GcwRank; import resources.datatables.Options; import resources.datatables.PlayerFlags; import resources.datatables.Professions; @@ -136,6 +141,48 @@ public class PlayerService implements INetworkDispatch { player.setTotalPlayTime((int) (player.getTotalPlayTime() + ((System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000))); player.setLastPlayTimeUpdate(System.currentTimeMillis()); core.collectionService.checkExplorationRegions(creature); + + // GCW rank progress + if (creature.getFaction().equals("rebel") || creature.getFaction().equals("imperial")){ + int oldrank = player.getCurrentRank(); + //int oldprogress = (int) ((player.getRankProgress() > 100) ? 100 : player.getRankProgress()); + int oldprogress = 0; + int oldpoints = player.getGcwPoints(); + int newrank = oldrank; + int newprogress = oldprogress; + int oldranktotal = 0; + int oldrankprogress = 0; + int newranktotal = 0; + int newrankprogress = 0; + + oldrankprogress = oldprogress * 50; + oldranktotal = 5000 * (oldrank - 1) + oldrankprogress; + + newprogress = (int) core.gcwService.helper(oldpoints, oldrank); + + if (newprogress < -2000) { + newprogress = -2000; + } + + newranktotal = oldranktotal + newprogress; + + if (oldrank == GcwRank.LIEUTENANT && newprogress < 0 && newranktotal < 30000) { + newranktotal = 29999; + } + + newrank = oldrank; + + if (newrank > GcwRank.GENERAL) { + newrank = GcwRank.GENERAL; + newranktotal = 12 * 5000 - 1; + } + + newrankprogress = newranktotal - (newrank - 1) * 5000; + newprogress = newrankprogress * 100 / 5000; + + player.setRankProgress((float) Math.floor(newprogress)); + } + } catch (Exception e) { e.printStackTrace(); } @@ -526,10 +573,19 @@ public class PlayerService implements INetworkDispatch { @SuppressWarnings("unchecked") public void sendCloningWindow(CreatureObject creature, final boolean pvpDeath) { - //if(creature.getPosture() != 14) - // return; + if(creature.getPosture() != 14) + return; List cloners = core.staticService.getCloningFacilitiesByPlanet(creature.getPlanet()); + + boolean invasionDeath = core.invasionService.checkInvasionDeath(creature); + + if (invasionDeath){ + if (core.invasionService.getAccordingCloners(creature).size()>0){ + cloners = core.invasionService.getAccordingCloners(creature); + } + } + Map cloneData = new HashMap(); Point3D position = creature.getWorldPosition(); @@ -542,9 +598,20 @@ public class PlayerService implements INetworkDispatch { } final long preDesignatedObjectId = (preDesignatedCloner != null) ? preDesignatedCloner.getObjectID() : 0; cloners.stream().filter(c -> c.getObjectID() != preDesignatedObjectId).forEach(c -> cloneData.put(c.getObjectID(), core.mapService.getClosestCityName(c))); + + Map listedCloneData = cloneData; + if (invasionDeath){ + if (core.invasionService.getAccordingCloners(creature).size()>0){ + listedCloneData = new HashMap(); + for (SWGObject cloner : core.invasionService.getAccordingCloners(creature)){ + listedCloneData.put(cloner.getObjectID(), cloner.getCustomName()); + } + } + } + final SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "@base_player:revive_title", "@base_player:clone_prompt_header", - cloneData, creature, null, 0); + listedCloneData, creature, null, 0); Vector returnList = new Vector(); returnList.add("List.lstList:SelectedRow"); @@ -577,10 +644,10 @@ public class PlayerService implements INetworkDispatch { } public void handleCloneRequest(CreatureObject creature, BuildingObject cloner, SpawnPoint spawnPoint, boolean pvpDeath) { - + CellObject cell = cloner.getCellByCellNumber(spawnPoint.getCellNumber()); - if(cell == null) + if(cell == null && !cloner.getTemplate().contains("shared_invisible_cloner")) return; creature.setPosture((byte) 0); @@ -599,7 +666,9 @@ public class PlayerService implements INetworkDispatch { creature.updateAllBuffs(); } - creature.setFactionStatus(0); + creature.setFactionStatus(FactionStatus.OnLeave); + creature.updatePvpStatus(); + core.buffService.addBuffToCreature(creature, "cloning_sickness", creature); } @@ -681,35 +750,36 @@ public class PlayerService implements INetworkDispatch { /* * Resets to level 1 */ - public void resetLevel(CreatureObject creature) { + public void resetLevel(CreatureObject creature, boolean unequipItems) { PlayerObject player = (PlayerObject) creature.getSlottedObject("ghost"); SWGObject inventory = creature.getSlottedObject("inventory"); - - try { - for (Long equipmentId : new ArrayList(creature.getEquipmentList())) { - - SWGObject equipment = core.objectService.getObject(equipmentId); - - if (equipment == null || equipment.getTemplate().startsWith("object/tangible/hair/")) { - continue; - } - - switch (equipment.getTemplate()) { - case "object/tangible/inventory/shared_character_inventory.iff": - case "object/tangible/inventory/shared_appearance_inventory.iff": - case "object/tangible/datapad/shared_character_datapad.iff": - case "object/tangible/bank/shared_character_bank.iff": - case "object/tangible/mission_bag/shared_mission_bag.iff": - case "object/weapon/creature/shared_creature_default_weapon.iff": - continue; - default: - creature.transferTo(creature, inventory, equipment); - } - } - } catch (Exception e) { - e.printStackTrace(); + + if (unequipItems) { + try { + for (Long equipmentId : new ArrayList(creature.getEquipmentList())) { + + SWGObject equipment = core.objectService.getObject(equipmentId); + + if (equipment == null || equipment.getTemplate().startsWith("object/tangible/hair/")) { + continue; + } + + switch (equipment.getTemplate()) { + case "object/tangible/inventory/shared_character_inventory.iff": + case "object/tangible/inventory/shared_appearance_inventory.iff": + case "object/tangible/datapad/shared_character_datapad.iff": + case "object/tangible/bank/shared_character_bank.iff": + case "object/tangible/mission_bag/shared_mission_bag.iff": + case "object/weapon/creature/shared_creature_default_weapon.iff": + continue; + default: + creature.transferTo(creature, inventory, equipment); + } + } + } catch (Exception e) { + e.printStackTrace(); + } } - //for (SWGObject equipment : creature.getAppearanceEquipmentList()) { //core.equipmentService.unequip(creature, equipment); //} @@ -793,7 +863,8 @@ public class PlayerService implements INetworkDispatch { if(level == 0) return; - resetLevel(creature); + if (!(creature.getLevel() <= (short) 1)) resetLevel(creature, true); + else resetLevel(creature, false); try { experienceTable = ClientFileManager.loadFile("datatables/player/player_level.iff", DatatableVisitor.class); diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index dd1c6171..874ac673 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -80,7 +80,9 @@ import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; import resources.objects.group.GroupObject; import resources.objects.harvester.HarvesterObject; +import resources.objects.installation.InstallationObject; import resources.objects.player.PlayerObject; +import resources.objects.staticobject.StaticObject; import resources.objects.tangible.TangibleObject; import resources.common.*; import resources.common.collidables.AbstractCollidable; @@ -281,12 +283,172 @@ public class SimulationService implements INetworkDispatch { public Vector getAllNearNPCs(int distance, SWGObject value ){ Vector foundCreatures = new Vector(); core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { - if (objecta instanceof CreatureObject) + if (objecta instanceof CreatureObject && objecta!=value) foundCreatures.add((CreatureObject)objecta); } ); return foundCreatures; } + + public Vector getAllNearPlayers(int distance, SWGObject value ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (objecta instanceof CreatureObject && objecta!=value) + if (((CreatureObject)objecta).isPlayer()) + foundCreatures.add((CreatureObject)objecta); + } + ); + return foundCreatures; + } + + public Vector getAllNearPlayers(int distance, Planet planet, Point3D pos ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(planet, pos.x, pos.z, distance).stream().forEach((objecta) -> { + if (objecta instanceof CreatureObject) + if (((CreatureObject)objecta).isPlayer()) + foundCreatures.add((CreatureObject)objecta); + } + ); + return foundCreatures; + } + + public Vector getAllNearNonSameFactionTargets(int distance, SWGObject center ){ + Vector foundTargets = new Vector(); + core.simulationService.get(center.getPlanet(), center.getWorldPosition().x, center.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (center.getObjectID()!=objecta.getObjectID()){ + String centerfaction = ""; + if (center instanceof CreatureObject) + centerfaction = ((CreatureObject)center).getFaction(); + if (center instanceof InstallationObject) + centerfaction = ((InstallationObject)center).getFaction(); + if (center instanceof TangibleObject) + centerfaction = ((TangibleObject)center).getFaction(); + + if (centerfaction.length()>0 && !(objecta instanceof StaticObject)){ + if (objecta.getObjectID()!=center.getObjectID() && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject) objecta,(TangibleObject) center)) + foundTargets.add((TangibleObject)objecta); + } + } + }); + return foundTargets; + } + + public Vector getAllNearNonSameFactionNPCs(int distance, SWGObject center ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(center.getPlanet(), center.getWorldPosition().x, center.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (center.getObjectID()!=objecta.getObjectID()){ + String centerfaction = ""; + if (center instanceof CreatureObject) + centerfaction = ((CreatureObject)center).getFaction(); + if (center instanceof InstallationObject) + centerfaction = ((InstallationObject)center).getFaction(); + if (center instanceof TangibleObject) + centerfaction = ((TangibleObject)center).getFaction(); + + if (centerfaction.length()>0 && objecta instanceof CreatureObject){ + if (objecta.getObjectID()!=center.getObjectID() && NGECore.getInstance().factionService.isFactionEnemy((CreatureObject) objecta,(TangibleObject) center)) + foundCreatures.add((CreatureObject)objecta); + } + } + }); + return foundCreatures; + } + + public Vector getAllNearNonSameFactionPlayers(int distance, SWGObject center ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(center.getPlanet(), center.getWorldPosition().x, center.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (center.getObjectID()!=objecta.getObjectID()){ + String centerfaction = ""; + if (center instanceof CreatureObject) + centerfaction = ((CreatureObject)center).getFaction(); + if (center instanceof InstallationObject) + centerfaction = ((InstallationObject)center).getFaction(); + if (center instanceof TangibleObject) + centerfaction = ((TangibleObject)center).getFaction(); + + if (centerfaction.length()>0 && objecta instanceof CreatureObject){ + if (((CreatureObject)objecta).isPlayer() && objecta.getObjectID()!=center.getObjectID() && NGECore.getInstance().factionService.isFactionEnemy((CreatureObject) objecta,(TangibleObject) center)) + foundCreatures.add((CreatureObject)objecta); + } + } + }); + return foundCreatures; + } + + public Vector getAllNearSameFactionNPCs(int distance, SWGObject center ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(center.getPlanet(), center.getWorldPosition().x, center.getWorldPosition().z, distance).stream().forEach((objecta) -> { + + String centerfaction = ""; + if (center instanceof CreatureObject) + centerfaction = ((CreatureObject)center).getFaction(); + if (center instanceof InstallationObject) + centerfaction = ((InstallationObject)center).getFaction(); + if (center instanceof TangibleObject) + centerfaction = ((TangibleObject)center).getFaction(); + + if (centerfaction.length()>0 && objecta instanceof CreatureObject){ + if (objecta.getObjectID()!=center.getObjectID() && NGECore.getInstance().factionService.isFactionAlly((TangibleObject) objecta,(TangibleObject) center)) + foundCreatures.add((CreatureObject)objecta); + } + }); + return foundCreatures; + } + + public Vector getAllNearSameFactionPlayers(int distance, Point3D centerPos, Planet planet, String factionName){ + Vector foundCreatures = new Vector(); + core.simulationService.get(planet, centerPos.x, centerPos.z, distance).stream().forEach((objecta) -> { + + if (factionName.length()>0 && objecta instanceof CreatureObject){ + if (((CreatureObject)objecta).isPlayer() && NGECore.getInstance().factionService.isFactionAlly(((CreatureObject) objecta).getFaction(),factionName)) + foundCreatures.add((CreatureObject)objecta); + } + }); + return foundCreatures; + } + + public Vector getAllNearSameFactionCreatures(int distance, Point3D centerPos, Planet planet, String factionName){ + Vector foundCreatures = new Vector(); + core.simulationService.get(planet, centerPos.x, centerPos.z, distance).stream().forEach((objecta) -> { + if (factionName.length()>0 && objecta instanceof CreatureObject){ + if (NGECore.getInstance().factionService.isFactionAlly(((CreatureObject) objecta).getFaction(),factionName)) + foundCreatures.add((CreatureObject)objecta); + } + }); + return foundCreatures; + } + + public Vector getAllNearTANOs(int distance, SWGObject value ){ + Vector foundTANOs = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (objecta instanceof TangibleObject && objecta!=value) + foundTANOs.add((TangibleObject)objecta); + } + ); + return foundTANOs; + } + + public Vector getAllNearNonSameFactionTANOs(int distance, SWGObject center ){ + Vector foundTANOs = new Vector(); + core.simulationService.get(center.getPlanet(), center.getWorldPosition().x, center.getWorldPosition().z, distance).stream().forEach((objecta) -> { + + //if (objecta.getTemplate().contains("shared_adv_turret_dish_sm_heat")){ + String centerfaction = ""; + if (center instanceof CreatureObject) + centerfaction = ((CreatureObject)center).getFaction(); + if (center instanceof InstallationObject) + centerfaction = ((InstallationObject)center).getFaction(); + if (center instanceof TangibleObject) + centerfaction = ((TangibleObject)center).getFaction(); + + if (centerfaction.length()>0 && objecta instanceof TangibleObject && !(objecta instanceof CreatureObject)){ + if (objecta.getObjectID()!=center.getObjectID() && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject) objecta,(TangibleObject) center)) + foundTANOs.add((TangibleObject)objecta); + } + + }); + return foundTANOs; + } public boolean move(SWGObject object, int oldX, int oldZ, int newX, int newZ) { if(quadTrees.get(object.getPlanet().getName()).remove(oldX, oldZ, object)) { @@ -705,6 +867,15 @@ public class SimulationService implements INetworkDispatch { add(object, newPosition.x, newPosition.z); } + if (object.getPlanet().getName().equals("talus") && object.getTemplate().contains("stormtrooper")){ +// float xx = object.getWorldPosition().x - newPosition.x; +// float zz = object.getWorldPosition().z - newPosition.z; +// float diff = (float) Math.sqrt(xx*xx+zz*zz); +// System.out.println(" ((CreatureObject)object).getSpeedMultiplierBase());: " + ((CreatureObject)object).getSpeedMultiplierBase()); +// System.out.println(" ((CreatureObject)object).getSpeedMultiplierMod());: " + ((CreatureObject)object).getSpeedMultiplierMod()); +// + } + UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), (short) (newPosition.x * 4 + 0.5), (short) (newPosition.y * 4 + 0.5), (short) (newPosition.z * 4 + 0.5), movementCounter + 1, getSpecialDirection(newOrientation), speed); List newAwareObjects = get(object.getPlanet(), newPosition.x, newPosition.z, 512); @@ -838,8 +1009,18 @@ public class SimulationService implements INetworkDispatch { float cos = (float) Math.cos(radians); WB_M44 rotationMatrix = new WB_M44(cos, 0, sin, 0, 0, 1, 0, 0, -sin, 0, cos, 0, 0, 0, 0, 1); - - WB_M44 modelSpace = translateMatrix.mult(rotationMatrix).inverse(); + + WB_M44 modelSpace = null; + try { + modelSpace = translateMatrix.mult(rotationMatrix).inverse(); + } catch (Exception ex){ + // It's usually a bank terminal causing this + //System.out.println("The object " + object.getTemplate() + " at x:" + object.getWorldPosition().x + " z:" + object.getWorldPosition().z + " causes a problem during modelspaceconversion. Can be safely ignored."); + if (modelSpace==null) + return new Ray(origin, new Vector3D(0,0,0)); + } + + float originX = (float) (modelSpace.m11 * origin.x + modelSpace.m12 * origin.y + modelSpace.m13 * origin.z + modelSpace.m14); float originY = (float) (modelSpace.m21 * origin.x + modelSpace.m22 * origin.y + modelSpace.m23 * origin.z + modelSpace.m24); @@ -1185,8 +1366,8 @@ public class SimulationService implements INetworkDispatch { public boolean checkLineOfSight(SWGObject object, Point3D position2) { long startTime = System.nanoTime(); - float heightOrigin = 1.f; - float heightDirection = 1.f; + float heightOrigin = 1.75f; + float heightDirection = 1.75f; if (object instanceof CreatureObject) { heightOrigin = getHeightOrigin((CreatureObject) object); @@ -1205,6 +1386,9 @@ public class SimulationService implements INetworkDispatch { continue; } + if (object.getTemplate().contains("_barricade") || object.getTemplate().contains("shared_dejarik_table_base")) + continue; + if (object.getTemplateData() != null && object.getTemplateData().getAttribute("collisionActionBlockFlags") != null) { int bit = (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags") & 255; @@ -1237,6 +1421,83 @@ public class SimulationService implements INetworkDispatch { return true; } + + public boolean checkLineOfSight2(SWGObject obj1, Point3D obj2) { + long startTime = System.nanoTime(); + + float heightOrigin = 1.75f; + float heightDirection = 1.75f; + + if(obj1 instanceof CreatureObject) + heightOrigin = getHeightOrigin((CreatureObject) obj1); + + Point3D position1 = obj1.getWorldPosition(); + Point3D position2 = obj2; + + Point3D origin = new Point3D(position1.x, position1.y + heightOrigin, position1.z); + Point3D end = new Point3D(position2.x, position2.y + heightDirection, position2.z); + float distance = position1.getDistance2D(position2); + + List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, (int) (distance + 10)); + + for(SWGObject object : inRangeObjects) { + + if(object == obj1) + continue; + + if (object.getTemplate().contains("_barricade") || object.getTemplate().contains("shared_dejarik_table_base")) + continue; + + if(object.getTemplateData() != null && object.getTemplateData().getAttribute("collisionActionBlockFlags") != null) { + int bit = (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags") & 255; + if(bit == (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags")) + continue; + } + + Ray ray = convertRayToModelSpace(origin, end, object); + + MeshVisitor visitor = object.getMeshVisitor(); + + if(visitor == null) + continue; + + List tris = visitor.getTriangles(); + + if(tris.isEmpty()) + continue; + + for(Mesh3DTriangle tri : tris) { + + if(ray.intersectsTriangle(tri, distance) != null) { + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (collided)"); + // System.out.println("Collided with " + object.getTemplate() + " X: " + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); + return false; + } + + } + + } + + List segments = new ArrayList(); + Line3D.splitIntoSegments(new Vec3D(position1.x, position1.y + 1, position1.z), new Vec3D(position2.x, position2.y + 1, position2.z), (float) 1, segments, true); + + for(Vec3D segment : segments) { + float y = segment.y; + + int height = (int) core.terrainService.getHeight(obj1.getPlanetId(), segment.x, segment.z); // round down to int + + if(height > y) { + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (terrain collision)"); + return false; + } + } + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (did not collide)"); + + return true; + + } + + public boolean checkLineOfSight(SWGObject obj1, SWGObject obj2) { long startTime = System.nanoTime(); if(obj1.getPlanet() != obj2.getPlanet()) @@ -1256,8 +1517,10 @@ public class SimulationService implements INetworkDispatch { } - float heightOrigin = 1.f; - float heightDirection = 1.f; +// float heightOrigin = 1.f; +// float heightDirection = 1.f; + float heightOrigin = 1.75f; + float heightDirection = 1.75f; if (obj2.getTemplate().equals("object/tangible/inventory/shared_character_inventory.iff")){ obj2 = obj2.getContainer(); // LOS message fix on corpse @@ -1283,6 +1546,9 @@ public class SimulationService implements INetworkDispatch { if(object == obj1 || object == obj2) continue; + if (object.getTemplate().contains("_barricade") || object.getTemplate().contains("shared_dejarik_table_base")) + continue; + if(object.getTemplateData() != null && object.getTemplateData().getAttribute("collisionActionBlockFlags") != null) { int bit = (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags") & 255; if(bit == (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags")) diff --git a/src/services/StaticService.java b/src/services/StaticService.java index 97be0a13..62b0ad61 100644 --- a/src/services/StaticService.java +++ b/src/services/StaticService.java @@ -59,9 +59,9 @@ public class StaticService implements INetworkDispatch { } public void spawnStatics() { - Config options = new Config(); - options.setFilePath("options.cfg"); - final boolean buildoutsDisabled = ((options.loadConfigFile() && options.getInt("LOAD.BUILDOUT_OBJECTS") == 0) ? true : false); + Config options = core.getOptions(); + + final boolean buildoutsDisabled = ((options != null && options.getInt("LOAD.BUILDOUT_OBJECTS") == 0) ? true : false); for (Planet planet : core.terrainService.getPlanetList()) { if (FileUtilities.doesFileExist("scripts/static_spawns/" + planet.getName())) { @@ -240,14 +240,13 @@ public class StaticService implements INetworkDispatch { public List getCloningFacilitiesByPlanet(Planet planet) { List objects = core.simulationService.get(planet, 0, 0, 8300); List cloners = new ArrayList(); - for (SWGObject obj : objects) { if(obj instanceof BuildingObject && (obj.getTemplate().contains("cloning_facility") || obj.getTemplate().contains("cloning_tatooine") || obj.getTemplate().contains("cloning_naboo") || obj.getTemplate().contains("cloning_corellia"))) { if(!obj.getTemplate().equals("object/building/general/shared_cloning_facility_general.iff")) cloners.add(obj); } } - + return cloners; } diff --git a/src/services/SurveyService.java b/src/services/SurveyService.java index 539af893..5bf32584 100644 --- a/src/services/SurveyService.java +++ b/src/services/SurveyService.java @@ -37,7 +37,6 @@ import resources.harvest.SurveyTool; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import resources.objects.resource.GalacticResource; -import resources.objects.resource.ResourceConcentration; import resources.objects.resource.ResourceContainerObject; import resources.objects.resource.ResourceRoot; import resources.objects.tangible.TangibleObject; diff --git a/src/services/TerrainService.java b/src/services/TerrainService.java index 8bea9b00..9266b84a 100644 --- a/src/services/TerrainService.java +++ b/src/services/TerrainService.java @@ -34,6 +34,7 @@ import resources.datatables.ClientPOIRadius; import services.playercities.ClientRegion; import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.DatatableVisitor; +import engine.resources.common.CRC; import engine.resources.config.Config; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; @@ -168,6 +169,16 @@ public class TerrainService { return null; } + public Planet getPlanetByCrc(int crc) { + for (int i = 0; i < planets.size(); i++) { + if (CRC.StringtoCRC(planets.get(i).getName().toLowerCase()) == crc) { + return planets.get(i); + } + } + + return null; + } + public Planet getPlanetByPath(String path) { for (int i = 0; i < planets.size(); i++) { if (planets.get(i).getPath().equals(path)) { @@ -197,11 +208,9 @@ public class TerrainService { if(planet.getSnapshotVisitor() != null) { Thread thread = new Thread(() -> { - Config config = new Config(); - config.setFilePath("options.cfg"); - boolean loaded = config.loadConfigFile(); - - if (loaded && config.getInt("LOAD.SNAPSHOT_OBJECTS") > 0) { + Config options = core.getOptions(); + + if (options != null && options.getInt("LOAD.SNAPSHOT_OBJECTS") > 0) { if (!core.getExcludedDevelopers().contains(System.getProperty("user.name"))){ try { core.objectService.loadSnapshotObjects(planet); @@ -211,17 +220,17 @@ public class TerrainService { } } - if (loaded && config.getInt("LOAD.BUILDOUT_OBJECTS") > 0) { - if (!core.getExcludedDevelopers().contains(System.getProperty("user.name"))){ - if (! config.keyExists("LOAD.BUILDOUT_ONLY_FOR")){ + if (options != null && options.getInt("LOAD.BUILDOUT_OBJECTS") > 0) { + if (!core.getExcludedDevelopers().contains(System.getProperty("user.name"))){ + if (! options.keyExists("LOAD.BUILDOUT_ONLY_FOR")){ try { core.objectService.loadBuildoutObjects(planet); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } - } else { - if (planet.getName().equals(config.getString("LOAD.BUILDOUT_ONLY_FOR"))){ - try { + } else { + if (planet.getName().trim().equals(options.getString("LOAD.BUILDOUT_ONLY_FOR").trim())){ + try { core.objectService.loadBuildoutObjects(planet); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); diff --git a/src/services/ai/AIActor.java b/src/services/ai/AIActor.java index f17a7741..20bc635b 100644 --- a/src/services/ai/AIActor.java +++ b/src/services/ai/AIActor.java @@ -59,7 +59,7 @@ public class AIActor { private CreatureObject creature; private Point3D spawnPosition; private volatile AIState currentState; - private CreatureObject followObject; + private TangibleObject followObject; private Vector movementPoints = new Vector(); private MobileTemplate mobileTemplate; private ScheduledExecutorService scheduler; @@ -86,14 +86,41 @@ public class AIActor { private ScheduledFuture movementFuture; private ScheduledFuture recoveryFuture; private ScheduledFuture despawnFuture; + private boolean patrolLoop = true; // default + private TangibleObject lastTarget = null; + private Point3D repositionLocation; + private long repositionStartTime = 0L; + private long actorID = 0L; + private static long autoActorID = 0L; + private boolean actorAlive = true; + private int progressionMarker = 0; + private boolean AIactive = true; public AIActor(CreatureObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler) { + actorID = autoActorID++; this.creature = creature; this.spawnPosition = spawnPosition; setLastPositionBeforeStateChange(spawnPosition); // just to make sure it's initialized this.scheduler = scheduler; creature.getEventBus().subscribe(this); this.currentState = new IdleState(); + initiateSchedules(); + } + + public AIActor(CreatureObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler, boolean aiactive) { + actorID = autoActorID++; + this.creature = creature; + this.spawnPosition = spawnPosition; + setLastPositionBeforeStateChange(spawnPosition); // just to make sure it's initialized + this.scheduler = scheduler; + creature.getEventBus().subscribe(this); + this.currentState = new IdleState(); + this.AIactive = aiactive; + initiateSchedules(); + } + + private void initiateSchedules(){ + setIntendedPrimaryAIState(this.currentState); // to switch back to after aggro regenTask = scheduler.scheduleAtFixedRate(() -> { try { @@ -112,41 +139,42 @@ public class AIActor { if(creature.getOption(Options.AGGRESSIVE)) { aggroCheckTask = scheduler.scheduleAtFixedRate(() -> { try { - - if(creature == null || creature.getObservers().isEmpty() || creature.isInCombat() || isStalking) - return; - if (creature.getAttachment("tamed")!=null){ - DevLog.debugout("Charon", "Pet AI", "aggroCheckTask tamed==1"); - return; - } - - if (creature.getCustomName().contains("baby")) - DevLog.debugout("Charon", "Pet AI", "baby aggroCheckTask should not be here " +creature.getAttachment("tamed")); - - creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 15)).forEach((obj) -> { - if(new Random().nextFloat() <= 0.5 || creature.isInCombat() || isStalking) { - /*if(mobileTemplate.isStalker()) { - setFollowObject((CreatureObject) obj); - setCurrentState(new StalkState()); - } else */ - - if (creature.getAttachment("IsBeingTamed")!=null) - return; - - if (obj instanceof CreatureObject){ - CreatureObject addedObject = (CreatureObject) obj; - if (addedObject.getCalledPet()!=null){ - CreatureObject calledPet = addedObject.getCalledPet(); - if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ - addDefender(calledPet); + if (AIactive){ + if(creature == null || creature.getObservers().isEmpty() || creature.isInCombat() || isStalking) + return; + if (creature.getAttachment("tamed")!=null){ + DevLog.debugoutai(this, "Charon", "Pet AI", "aggroCheckTask tamed==1"); + return; + } + + if (creature.getCustomName().contains("baby")) + DevLog.debugoutai(this, "Charon", "Pet AI", "baby aggroCheckTask should not be here " +creature.getAttachment("tamed")); + + creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 15)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat() || isStalking) { + /*if(mobileTemplate.isStalker()) { + setFollowObject((CreatureObject) obj); + setCurrentState(new StalkState()); + } else */ + + if (creature.getAttachment("IsBeingTamed")!=null) + return; + + if (obj instanceof CreatureObject){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ + addDefender(addedObject); } } - if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ - addDefender(addedObject); - } } - } - }); + }); + } } catch (Exception e) { e.printStackTrace(); } @@ -155,61 +183,66 @@ public class AIActor { if(creature.getFaction().length()>0 || !creature.getOption(Options.AGGRESSIVE)) { factionCheckTask = scheduler.scheduleAtFixedRate(() -> { try { - - if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || creature.getObservers().isEmpty() || creature.isInCombat()) - return; - - creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 15)).forEach((obj) -> { - if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { - DevLog.debugout("Charon", "CHECK faction creature ", "added " + creature.getFaction()); - DevLog.debugout("Charon", "CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); - DevLog.debugout("Charon", "CHECK factionCheckTask", "added " + obj.getCustomName()); - DevLog.debugout("Charon", "CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); - if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ - CreatureObject addedObject = (CreatureObject) obj; - if (addedObject.getCalledPet()!=null){ - CreatureObject calledPet = addedObject.getCalledPet(); - if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ - addDefender(calledPet); - } - } - if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ - addDefender(addedObject); - DevLog.debugout("Charon", "faction creature ", "added " + creature.getFaction()); - DevLog.debugout("Charon", "faction obj", "added " + ((TangibleObject)obj).getFaction()); - DevLog.debugout("Charon", "factionCheckTask", "added " + obj.getCustomName()); - } + if (AIactive){ + // this is difficult, should NPC not fight when no player is near? || creature.getObservers().isEmpty() + if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || creature.isInCombat()) + return; + if(this.getFollowObject() != null){ // Don't search if actor has valid target + CreatureObject addedCreature = null; + TangibleObject addedObject = null; + if (this.getFollowObject() instanceof TangibleObject){ + addedObject = (TangibleObject) this.getFollowObject(); + if (addedObject.getConditionDamage()>=addedObject.getMaximumCondition()) + return; + } + if (this.getFollowObject() instanceof CreatureObject){ + addedCreature = (CreatureObject) this.getFollowObject(); + if (addedCreature.getPosture() != 13 && addedCreature.getPosture() != 14) + return; } } - }); - - NGECore.getInstance().simulationService.getAllNearNPCs(15, creature).forEach((obj) -> { - if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { - DevLog.debugout("Charon", "CHECK faction creature ", "added " + creature.getFaction()); - DevLog.debugout("Charon", "CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); - DevLog.debugout("Charon", "CHECK factionCheckTask", "added " + obj.getCustomName()); - DevLog.debugout("Charon", "CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); - if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ - CreatureObject addedObject = (CreatureObject) obj; - if (addedObject.getCalledPet()!=null){ - CreatureObject calledPet = addedObject.getCalledPet(); - if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ - addDefender(calledPet); + + // Check for near targets + float[] closestDist = {9999F}; + TangibleObject[] closestCreature = {null}; + + NGECore.getInstance().simulationService.getAllNearNonSameFactionTargets(15, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { + if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (CreatureObject)obj)){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (NGECore.getInstance().aiService.distanceSquared2D(creature.getWorldPosition(), obj.getWorldPosition()) @@ -250,9 +287,18 @@ public class AIActor { } } - public void removeDefender(CreatureObject defender) { + public void removeDefender(TangibleObject defender) { + if (defender==null){ +// damageMap.keySet().remove(null); +// damageMap.values().remove(null); + //ToDo: Remove those empty defenders somehow +// if (damageMap.containsKey(null)) +// damageMap.remove(null); + return; + } creature.removeDefender(defender); - damageMap.remove(defender); + if (damageMap.containsKey(defender)) + damageMap.remove(defender); defender.removeDefender(creature); if(followObject == defender) { setFollowObject(getHighestDamageDealer()); @@ -285,17 +331,18 @@ public class AIActor { if(this.currentState != null) doStateAction(this.currentState.onExit(this)); this.currentState = currentState; + DevLog.debugoutai(this,"Charon", "AI Actor setCurrentState", "setCurrentState " + currentState.getClass().getName()); doStateAction(currentState.onEnter(this)); } catch (Exception e) { e.printStackTrace(); } } - public CreatureObject getFollowObject() { + public TangibleObject getFollowObject() { return followObject; } - public void setFollowObject(CreatureObject followObject) { + public void setFollowObject(TangibleObject followObject) { this.followObject = followObject; } @@ -316,23 +363,39 @@ public class AIActor { } public void scheduleMovement() { + // Catch current state BEFORE waiting 500ms for execution, + // as the state could have changed in that time resulting in + // undesired additional movement loops + AIState caughtAIState = currentState; + if (currentState==null) + return; + if (!actorAlive) + return; movementFuture = scheduler.schedule(() -> { try { if (creature==null){ destroyActor(); return; } - doStateAction(currentState.move(AIActor.this)); + if (caughtAIState!=null && currentState!=null){ + if (caughtAIState.getClass().equals(currentState.getClass())) + doStateAction(caughtAIState.move(AIActor.this)); + } } catch (Exception e) { + //System.out.println("Exception in scheduleMovement"); e.printStackTrace(); } }, 500, TimeUnit.MILLISECONDS); } public void scheduleRecovery() { + AIState caughtAIState = currentState; + if (!actorAlive) + return; recoveryFuture = scheduler.schedule(() -> { try { - doStateAction(currentState.recover(AIActor.this)); + if (caughtAIState.getClass().equals(currentState.getClass())) + doStateAction(caughtAIState.recover(AIActor.this)); } catch (Exception e) { e.printStackTrace(); } @@ -345,11 +408,18 @@ public class AIActor { @Handler public void handleDamage(DamageTaken event) { - CreatureObject attacker = event.attacker; + CreatureObject attacker = (CreatureObject)event.attacker; if(damageMap.containsKey(attacker)) damageMap.put(attacker, damageMap.get(attacker) + event.damage); else damageMap.put(attacker, event.damage); + + // Put AI into combat state if it is not yet and damaged + if (!creature.isInCombat()){ + creature.setInCombat(true); + if (this.getHighestDamageDealer()!=null) + addDefender(this.getHighestDamageDealer()); + } } public Map getDamageMap() { @@ -408,7 +478,8 @@ public class AIActor { } switch(result) { - + + case StateResult.DEAD: setCurrentState(new DeathState()); break; @@ -459,17 +530,24 @@ public class AIActor { try { damageMap.clear(); followObject = null; - creature.setAttachment("AI", null); - NGECore.getInstance().objectService.destroyObject(creature); + NGECore.getInstance().objectService.destroyObject(creature); } catch (Exception e) { e.printStackTrace(); } } - }, 2, TimeUnit.MINUTES); + //}, 2, TimeUnit.MINUTES); + }, 10, TimeUnit.SECONDS); } public void destroyActor(){ creature.getEventBus().unsubscribe(this); + if (creature!=null){ + if (despawnFuture!=null){ + despawnFuture.cancel(true); + despawnFuture = null; + } + } + // Make sure to kill all AI helper threads if (aggroCheckTask!=null) aggroCheckTask.cancel(true); @@ -484,11 +562,7 @@ public class AIActor { if (movementFuture!=null){ recoveryFuture.cancel(true); recoveryFuture = null; - } - if (despawnFuture!=null){ - despawnFuture.cancel(true); - despawnFuture = null; - } + } } public void cancelAggro(){ @@ -627,5 +701,100 @@ public class AIActor { Point3D lastPositionBeforeStateChange) { this.lastPositionBeforeStateChange = lastPositionBeforeStateChange; } + + public boolean isPatrolLoop() { + return patrolLoop; + } + + public void setPatrolLoop(boolean patrolLoop) { + this.patrolLoop = patrolLoop; + } + + public TangibleObject getLastTarget() { + return lastTarget; + } + + public void setLastTarget(TangibleObject lastTarget) { + this.lastTarget = lastTarget; + } + + public Point3D getRepositionLocation() { + return repositionLocation; + } + + public void setRepositionLocation(Point3D repositionLocation) { + this.repositionLocation = repositionLocation; + } + + public long getRepositionStartTime() { + return repositionStartTime; + } + + public void setRepositionStartTime(long repositionStartTime) { + this.repositionStartTime = repositionStartTime; + } + + public long getActorID() { + return actorID; + } + + public boolean isActorAlive() { + return actorAlive; + } + + public void setActorAlive(boolean actorAlive) { + this.actorAlive = actorAlive; + } + + public int getProgressionMarker() { + return progressionMarker; + } + + public void setProgressionMarker(int progressionMarker) { + this.progressionMarker = progressionMarker; + } + + public boolean isAIactive() { + return AIactive; + } + + public void setAIactive(boolean aIactive) { + AIactive = aIactive; + } + public void prepareDeletion() { + if(this.creature!=null){ + lastPositionBeforeStateChange = this.creature.getWorldPosition(); + this.creature.getDefendersList().clear(); + this.setFollowObject(null); + } + this.setIntendedPrimaryAIState(new IdleState()); + patrolPoints.clear(); + movementPoints.clear(); + actorAlive = false; // stop moving + AIactive = false; // stop reacting to attacks + } + + public void cloneActor(AIActor oldActor) { + AIactive = oldActor.isAIactive(); + isStalking = oldActor.isStalking(); + patrolPoints = oldActor.getPatrolPoints(); + loiterDestType = oldActor.getLoiterDestType(); + loiterDestination = oldActor.getLoiterDestination(); + minLoiterDist = oldActor.getMinLoiterDist(); + maxLoiterDist = oldActor.getMaxLoiterDist(); + waitState = oldActor.getWaitState(); + waitStartTime = oldActor.getWaitStartTime(); + patrolLoop =oldActor.isPatrolLoop(); + intendedPrimaryAIState = oldActor.getIntendedPrimaryAIState(); + try { + setCurrentState(intendedPrimaryAIState.getClass().newInstance()); + } catch (InstantiationException e) { + System.out.println("Aiactor cloning failed InstantiationException"); + e.printStackTrace(); + } catch (IllegalAccessException e) { + System.out.println("Aiactor cloning failed IllegalAccessException"); + e.printStackTrace(); + } + } } diff --git a/src/services/ai/AIService.java b/src/services/ai/AIService.java index 45ad9279..162b09b1 100644 --- a/src/services/ai/AIService.java +++ b/src/services/ai/AIService.java @@ -21,8 +21,13 @@ ******************************************************************************/ package services.ai; +import java.lang.reflect.Method; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.Random; import java.util.Vector; @@ -33,18 +38,21 @@ import resources.datatables.GcwType; import resources.objects.creature.CreatureObject; import resources.objects.group.GroupObject; import resources.objects.player.PlayerObject; +import resources.objects.tangible.TangibleObject; import services.ai.states.AIState; import services.ai.states.IdleState; import services.ai.states.LoiterState; import services.ai.states.PatrolState; import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; +import engine.resources.service.INetworkDispatch; import main.NGECore; public class AIService { @SuppressWarnings("unused") private Vector aiActors = new Vector(); private NGECore core; + private TangibleObject checkerAI = null; public AIService(NGECore core) { this.core = core; @@ -54,6 +62,8 @@ public class AIService { // TODO: implement cell pathfinding, returning straight line for now Vector path = new Vector(); + if (pointA==null || pointB==null) + return path; path.add(pointA); float x = pointB.x - 1 + new Random().nextFloat(); float z = pointB.z - 1 + new Random().nextFloat(); @@ -169,6 +179,13 @@ public class AIService { } } + public void setPatrolLoop(CreatureObject creature, boolean value){ + AIActor actor = (AIActor) creature.getAttachment("AI"); + if (actor==null) + return; + actor.setPatrolLoop(value); + } + public void setPatrol(CreatureObject creature, Vector patrolpoints){ AIActor actor = (AIActor) creature.getAttachment("AI"); if (actor==null) @@ -178,6 +195,8 @@ public class AIService { AIState intendedPrimaryAIState = new PatrolState(); actor.setIntendedPrimaryAIState(intendedPrimaryAIState); actor.setCurrentState(intendedPrimaryAIState); + actor.setCurrentState(intendedPrimaryAIState); + actor.setCurrentState(intendedPrimaryAIState); } public void setPatrol(CreatureObject creature, boolean active){ @@ -209,6 +228,95 @@ public class AIService { actor.setCurrentState(intendedPrimaryAIState); } + public void setCheckAI(TangibleObject checker){ + checkerAI = checker; + } + + public TangibleObject getCheckAI(){ + return this.checkerAI; + } + + public float distanceSquared2D(Point3D p2, Point3D p1){ + return (p2.x - p1.x) * (p2.x - p1.x) + (p2.z - p1.z) * (p2.z - p1.z); + } + + public float distanceSquared(Point3D p2, Point3D p1){ + return (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y) + (p2.z - p1.z) * (p2.z - p1.z); + } + + public void waitForEvent(AIActor actor, INetworkDispatch service, String serviceMethodName, boolean expectedValue, Class nextStateClass){ + + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + final Future[] wfe = {null}; + wfe[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + Class noParams[] = {}; + Method m = service.getClass().getMethod(serviceMethodName, noParams); + boolean value = (boolean) m.invoke(service); + if (value==expectedValue){ + actor.setCurrentState((AIState)nextStateClass.newInstance()); + System.out.println("condition true waitForEvent! " + nextStateClass.getName()); + Thread.yield(); + wfe[0].cancel(false); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }, 10, 3000, TimeUnit.MILLISECONDS); + } + + public void waitForEvent(AIActor actor, INetworkDispatch service, String serviceMethodName, int expectedValue, Class nextStateClass){ + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + final Future[] wfe = {null}; + wfe[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + try { + Class noParams[] = {}; + Method m = service.getClass().getMethod(serviceMethodName, noParams); + int number = (int) m.invoke(service); + if (number==expectedValue){ + actor.setCurrentState((AIState)nextStateClass.newInstance()); + Thread.yield(); + wfe[0].cancel(false); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }, 10, 3000, TimeUnit.MILLISECONDS); + } + + // ToDo: Make an overloaded method with params + public void waitForEvent(INetworkDispatch service, String serviceMethodName, Object[] params){ + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + final Future[] wfe = {null}; + wfe[0] = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + boolean condition = true; + Class noParams[] = {}; + Method m = service.getClass().getMethod(serviceMethodName, noParams); + m.invoke(service); + + if (condition){ + Thread.yield(); + wfe[0].cancel(false); + } + // do something + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 10, 2000, TimeUnit.MILLISECONDS); + } + public void logAI(String logMsg){ if (checkDeveloperIdentity()){ System.err.println("AI-LOG: " + logMsg); diff --git a/src/services/ai/LairActor.java b/src/services/ai/LairActor.java index 1bb1e4b8..ef263b2d 100644 --- a/src/services/ai/LairActor.java +++ b/src/services/ai/LairActor.java @@ -33,6 +33,7 @@ import resources.objects.tangible.TangibleObject; import services.combat.CombatEvents.DamageTaken; import tools.DevLog; +@SuppressWarnings("unused") public class LairActor { private Vector creatures = new Vector(); @@ -86,8 +87,8 @@ public class LairActor { spawnNewCreatures(); for(AIActor ai : creatures) { - ai.addDefender(event.attacker); - event.attacker.addDefender(ai.getCreature()); + ai.addDefender((CreatureObject)event.attacker); + ((CreatureObject)event.attacker).addDefender(ai.getCreature()); } @@ -163,7 +164,6 @@ public class LairActor { } - @SuppressWarnings("unused") private void healLair() { if(lairObject.getConditionDamage() == 0 || creatures.isEmpty()) diff --git a/src/services/ai/TurretAIActor.java b/src/services/ai/TurretAIActor.java new file mode 100644 index 00000000..4773ec34 --- /dev/null +++ b/src/services/ai/TurretAIActor.java @@ -0,0 +1,599 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai; + +import java.util.Map; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import main.NGECore; +import net.engio.mbassy.listener.Handler; +import engine.clients.Client; +import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.datatables.Options; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; +import resources.objects.tangible.TangibleObject; +import services.ai.states.TurretAIState; +import services.ai.states.TurretAIState.StateResult; +import services.ai.states.AIState; +import services.ai.states.TurretAttackState; +import services.ai.states.TurretIdleState; +import services.combat.CombatEvents.DamageTaken; +import services.spawn.MobileTemplate; +import tools.DevLog; +import resources.datatables.FactionStatus; + +import java.util.Random; + +@SuppressWarnings("unused") +public class TurretAIActor { + + private TangibleObject creature; + private Point3D spawnPosition; + private volatile TurretAIState currentState; + private TangibleObject followObject; + private Vector movementPoints = new Vector(); + private MobileTemplate mobileTemplate; + private ScheduledExecutorService scheduler; + private Map damageMap = new ConcurrentHashMap(); + private volatile boolean hasReachedPosition; + private long lastAttackTimestamp; + private ScheduledFuture regenTask; + private ScheduledFuture aggroCheckTask; + private ScheduledFuture factionCheckTask; + private boolean isStalking = false; + private byte milkState = 0; + private boolean hasBeenHarvested = false; + private Vector patrolPoints = new Vector(); + private int patrolPointIndex = 0; + private String loiterDestType = "LOITER"; + private Point3D loiterDestination; + private Point3D originPosition; + private float minLoiterDist; + private float maxLoiterDist; + private String waitState = "NO"; + private long waitStartTime = 0L; + private TurretAIState intendedPrimaryTurretAIState; + private Point3D lastPositionBeforeStateChange; + private boolean patrolLoop = true; // default + private ScheduledFuture recoveryFuture; + + + public TurretAIActor(TangibleObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler) { + this.creature = creature; + this.spawnPosition = spawnPosition; + setLastPositionBeforeStateChange(spawnPosition); // just to make sure it's initialized + this.scheduler = scheduler; + creature.getEventBus().subscribe(this); + this.currentState = new TurretIdleState(); + setIntendedPrimaryTurretAIState(this.currentState); // to switch back to after aggro + + if(creature.getOption(Options.AGGRESSIVE)) { + aggroCheckTask = scheduler.scheduleAtFixedRate(() -> { + try { + + if(creature == null || creature.getObservers().isEmpty() || creature.isInCombat() || isStalking) + return; + if (creature.getAttachment("tamed")!=null){ + DevLog.debugoutai(this, "Charon", "Pet AI", "aggroCheckTask tamed==1"); + return; + } + + if (creature.getCustomName().contains("baby")) + DevLog.debugoutai(this, "Charon", "Pet AI", "baby aggroCheckTask should not be here " +creature.getAttachment("tamed")); + + creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 60)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat() || isStalking) { + /*if(mobileTemplate.isStalker()) { + setFollowObject((CreatureObject) obj); + setCurrentState(new StalkState()); + } else */ + + if (creature.getAttachment("IsBeingTamed")!=null) + return; + + if (obj instanceof CreatureObject){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ + addDefender(addedObject); + } + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }, 0, 2000, TimeUnit.MILLISECONDS); + } + if(creature.getFaction().length()>0 || !creature.getOption(Options.AGGRESSIVE)) { + factionCheckTask = scheduler.scheduleAtFixedRate(() -> { + //System.out.println("Turret faction thread"); + try { + + if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || creature.getObservers().isEmpty() || creature.isInCombat()) + return; + + creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 60)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { +// DevLog.debugout("Charon", "TURRET CHECK faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TURRET CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14 && ! addedObject.getOption(Options.INVULNERABLE)){ + addDefender(addedObject); +// DevLog.debugout("Charon", "TURRET faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET factionCheckTask", "added " + obj.getCustomName()); + } + + } + } + }); + + NGECore.getInstance().simulationService.getAllNearNonSameFactionNPCs(60, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { +// DevLog.debugout("Charon", "TURRET CHECK faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TURRET CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14 & ! calledPet.getOption(Options.INVULNERABLE)){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14 & ! addedObject.getOption(Options.INVULNERABLE)){ + addDefender(addedObject); +// DevLog.debugout("Charon", "TURRET faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET factionCheckTask", "added " + obj.getCustomName()); + } + } + } + }); + + NGECore.getInstance().simulationService.getAllNearNonSameFactionTANOs(60, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { +// DevLog.debugout("Charon", "TANO CHECK faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TANO CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TANO CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TANO CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof TangibleObject && !(obj instanceof CreatureObject) && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + TangibleObject addedObject = (TangibleObject) obj; + addDefender(addedObject); + DevLog.debugoutai(this, "Charon", "TANO faction creature ", "added " + creature.getFaction()); + DevLog.debugoutai(this, "Charon", "TANO faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugoutai(this, "Charon", "TANO factionCheckTask", "added " + obj.getCustomName()); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }, 0, 1000, TimeUnit.MILLISECONDS); + + } + } + + public TangibleObject getCreature() { + return creature; + } + + public void setCreature(CreatureObject creature) { + this.creature = creature; + } + + public Point3D getSpawnPosition() { + return spawnPosition; + } + + public void setSpawnPosition(Point3D spawnPosition) { + this.spawnPosition = spawnPosition; + } + +// public void addDefender(CreatureObject defender) { +// addDefender(defender, false); +// } + public void addDefender(TangibleObject defender) { + addDefender(defender, false); + } + + + public void addDefender(TangibleObject defender, boolean isAssisting) { + creature.addDefender(defender); + if(followObject == null) + setFollowObject(defender); + setCurrentState(new TurretAttackState()); +// if(!isAssisting) { +// NGECore.getInstance().simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 38).stream().filter((obj) -> +// obj instanceof CreatureObject && +// obj.getAttachment("AI") != null && +// ((TurretAIActor) obj.getAttachment("AI")).getMobileTemplate().getSocialGroup().equals(getMobileTemplate().getSocialGroup()) && +// obj.inRange(creature.getWorldPosition(), ((TurretAIActor) obj.getAttachment("AI")).getMobileTemplate().getAssistRange()) +// ).forEach((obj) -> ((TurretAIActor) obj.getAttachment("AI")).addDefender(defender, true)); +// } + } + + public void removeDefender(TangibleObject defender) { + creature.removeDefender(defender); + damageMap.remove(defender); + defender.removeDefender(creature); + if(followObject == defender) { + setFollowObject(getHighestDamageDealer()); + if(creature.getDefendersList().size() == 0) + setCurrentState(new TurretIdleState()); + } + } + + public CreatureObject getHighestDamageDealer() { + CreatureObject highestDamageDealer = null; + highestDamageDealer = damageMap.keySet().stream().max((c1, c2) -> damageMap.get(c1) - damageMap.get(c2)).orElse(null); + // return first defender if no damage has been dealt + if(highestDamageDealer == null) { + for(TangibleObject tangible : creature.getDefendersList().toArray(new TangibleObject[]{})) { + if(tangible instanceof CreatureObject) + return (CreatureObject) tangible; + } + } + return highestDamageDealer; + } + + public TurretAIState getCurrentState() { + return currentState; + } + + public void setCurrentState(TurretAIState currentState) { + try { + if(currentState.getClass() == this.currentState.getClass()) + return; + if(this.currentState != null) + doStateAction(this.currentState.onExit(this)); + this.currentState = currentState; + doStateAction(currentState.onEnter(this)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public TangibleObject getFollowObject() { + return followObject; + } + + public void setFollowObject(TangibleObject followObject) { + this.followObject = followObject; + } + + public Vector getMovementPoints() { + return movementPoints; + } + + public void setMovementPoints(Vector movementPoints) { + this.movementPoints = movementPoints; + } + + public MobileTemplate getMobileTemplate() { + return mobileTemplate; + } + + public void setMobileTemplate(MobileTemplate mobileTemplate) { + this.mobileTemplate = mobileTemplate; + } + + public void scheduleRecovery() { + TurretAIState caughtAIState = currentState; + recoveryFuture = scheduler.schedule(() -> { + try { + if (caughtAIState.getClass().equals(currentState.getClass())) + doStateAction(currentState.recover(TurretAIActor.this)); + } catch (Exception e) { + e.printStackTrace(); + } + }, 2000, TimeUnit.MILLISECONDS); + } + + public void setNextPosition(Point3D position) { + movementPoints.add(0, position); + } + + @Handler + public void handleDamage(DamageTaken event) { + CreatureObject attacker = (CreatureObject)event.attacker; + if(damageMap.containsKey(attacker)) + damageMap.put(attacker, damageMap.get(attacker) + event.damage); + else + damageMap.put(attacker, event.damage); + } + + public Map getDamageMap() { + return damageMap; + } + + public boolean hasReachedPosition() { + return hasReachedPosition; + } + + public void setHasReachedPosition(boolean hasReachedPosition) { + this.hasReachedPosition = hasReachedPosition; + } + + public void faceObject(SWGObject object) { + // Null checks due to a null error at: float direction = + if (object == null) DevLog.debugout("Charon", "AI Actor", "faceObject object is NULL"); + if (creature == null) DevLog.debugout("Charon", "AI Actor", "faceObject creature is NULL"); + if (object.getWorldPosition() == null) DevLog.debugout("Charon", "AI Actor", "faceObject object's position is NULL"); + if (creature.getWorldPosition() == null) DevLog.debugout("Charon", "AI Actor", "faceObject creature's position is NULL"); + + float direction = (float) Math.atan2(object.getWorldPosition().x - creature.getWorldPosition().x, object.getWorldPosition().z - creature.getWorldPosition().z); + if(direction < 0) + direction = (float) (2 * Math.PI + direction); + if(Math.abs(direction - creature.getRadians()) < 0.05) + return; + Quaternion quaternion = new Quaternion((float) Math.cos(direction / 2), 0, (float) Math.sin(direction / 2), 0); + if (quaternion.y < 0.0f && quaternion.w > 0.0f) { + quaternion.y *= -1; + quaternion.w *= -1; + } + if(creature.getContainer() instanceof CellObject) + NGECore.getInstance().simulationService.moveObject(creature, creature.getPosition(), quaternion, creature.getMovementCounter(), 0, (CellObject) creature.getContainer()); + else + NGECore.getInstance().simulationService.moveObject(creature, creature.getPosition(), quaternion, creature.getMovementCounter(), 0, null); + + } + + public long getLastAttackTimestamp() { + return lastAttackTimestamp; + } + + public void setLastAttackTimestamp(long lastAttackTimestamp) { + this.lastAttackTimestamp = lastAttackTimestamp; + } + + public long getTimeSinceLastAttack() { + return System.currentTimeMillis() - getLastAttackTimestamp(); + } + + public void doStateAction(byte result) { + + if (creature==null){ + destroyActor(); + return; + } + + switch(result) { + + case StateResult.DEAD: + destroyActor(); + break; + case StateResult.FINISHED: + case StateResult.UNFINISHED: + return; + case StateResult.IDLE: + setCurrentState(new TurretIdleState()); + return; + + //case StateResult.NONE: + // System.out.println("State action returned error result"); + + } + + } + + public void scheduleDespawn() { + // Sometimes these tasks are null? + + try { + if (aggroCheckTask!=null) + aggroCheckTask.cancel(true); + if (factionCheckTask!=null) + factionCheckTask.cancel(true); + } catch(Exception e) { + + } + + try { + regenTask.cancel(true); + } catch(Exception e) { + + } + + } + + public void destroyActor(){ + creature.getEventBus().unsubscribe(this); + // Make sure to kill all AI helper threads + if (aggroCheckTask!=null) + aggroCheckTask.cancel(true); + if (factionCheckTask!=null) + factionCheckTask.cancel(true); + if (regenTask!=null) + regenTask.cancel(true); + } + + public void cancelAggro(){ + try { + aggroCheckTask.cancel(true); + } catch(Exception e) { + } + } + + public ScheduledFuture getRegenTask() { + return regenTask; + } + + public void setRegenTask(ScheduledFuture regenTask) { + this.regenTask = regenTask; + } + + public boolean isStalking() { + return isStalking; + } + + public void setStalking(boolean isStalking) { + this.isStalking = isStalking; + } + + public byte getMilkState() { + synchronized(creature.getMutex()) { + return milkState; + } + } + + public void setMilkState(byte milkState) { + synchronized(creature.getMutex()) { + this.milkState = milkState; + } + } + + public boolean hasBeenHarvested() { + synchronized(creature.getMutex()) { + return hasBeenHarvested; + } + } + + public void setHasBeenHarvested(boolean hasBeenHarvested) { + synchronized(creature.getMutex()) { + this.hasBeenHarvested = hasBeenHarvested; + } + } + + public void setPatrolPoints(Vector patrolPoints){ + this.patrolPoints = patrolPoints; + //setMovementPoints(patrolPoints); + } + + public int getPatrolPointIndex() { + return patrolPointIndex; + } + + public void setPatrolPointIndex(int patrolPointIndex) { + this.patrolPointIndex = patrolPointIndex; + } + + public Point3D getLoiterDestination() { + return loiterDestination; + } + + public void setLoiterDestination(Point3D loiterDestination) { + this.loiterDestination = loiterDestination; + } + + public Point3D getOriginPosition() { + return originPosition; + } + + public void setOriginPosition(Point3D originPosition) { + this.originPosition = originPosition; + } + + public String getLoiterDestType() { + return loiterDestType; + } + + public void setLoiterDestType(String loiterDestType) { + this.loiterDestType = loiterDestType; + } + + public float getMinLoiterDist() { + return minLoiterDist; + } + + public void setMinLoiterDist(float minLoiterDist) { + this.minLoiterDist = minLoiterDist; + } + + public float getMaxLoiterDist() { + return maxLoiterDist; + } + + public void setMaxLoiterDist(float maxLoiterDist) { + this.maxLoiterDist = maxLoiterDist; + } + + public String getWaitState() { + return waitState; + } + + public void setWaitState(String waitState) { + this.waitState = waitState; + } + + public long getWaitStartTime() { + return waitStartTime; + } + + public void setWaitStartTime(long waitStartTime) { + this.waitStartTime = waitStartTime; + } + + public Vector getPatrolPoints() { + return patrolPoints; + } + + public TurretAIState getIntendedPrimaryTurretAIState() { + return intendedPrimaryTurretAIState; + } + + public void setIntendedPrimaryTurretAIState(TurretAIState intendedPrimaryTurretAIState) { + this.intendedPrimaryTurretAIState = intendedPrimaryTurretAIState; + } + + public Point3D getLastPositionBeforeStateChange() { + return lastPositionBeforeStateChange; + } + + public void setLastPositionBeforeStateChange( + Point3D lastPositionBeforeStateChange) { + this.lastPositionBeforeStateChange = lastPositionBeforeStateChange; + } + + public boolean isPatrolLoop() { + return patrolLoop; + } + + public void setPatrolLoop(boolean patrolLoop) { + this.patrolLoop = patrolLoop; + } + +} diff --git a/src/services/ai/states/AIState.java b/src/services/ai/states/AIState.java index ac25ae37..b1f4a93c 100644 --- a/src/services/ai/states/AIState.java +++ b/src/services/ai/states/AIState.java @@ -27,12 +27,16 @@ import java.util.Vector; import main.NGECore; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; +import engine.resources.service.INetworkDispatch; import resources.common.SpawnPoint; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; import services.ai.AIActor; +import tools.DevLog; +@SuppressWarnings("unused") public abstract class AIState { public abstract byte onEnter(AIActor actor) throws Exception; @@ -40,6 +44,11 @@ public abstract class AIState { public abstract byte move(AIActor actor) throws Exception; public abstract byte recover(AIActor actor) throws Exception; + public static long lastExecutionTime = 0L; + public static long stateID = 0L; + public static long autoStateID = 0L; + + public enum StateResult {; // default error state result @@ -54,11 +63,187 @@ public abstract class AIState { public static final byte PATROL = 5; public static final byte LOITER = 6; public static final byte FOLLOW = 7; + public static final byte ATTACK = 8; } public boolean findNewPosition(AIActor actor, float speed, float stopDistance, Point3D newPosition) { + speed *= 0.5; // 2 updates per second + CreatureObject creature = actor.getCreature(); + if (!actor.isActorAlive()) + return false; // Suppress any further movement when actor is destroyed to prevent reappearing + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + Vector patrolPoints = actor.getPatrolPoints(); + CellObject cell = null; + //while(!finished && movementPoints.size() != 0) { + + if ((!(actor.getCurrentState() instanceof FollowState)) && movementPoints.size() == 0 && patrolPoints.size() == 0) { + DevLog.debugoutai(actor, "Charon", "AI State findnewpos", "Breakout1"); + return false; + } + + if (movementPoints.size() != 0){ + try{ + targetPosition = movementPoints.firstElement(); + } catch (NoSuchElementException e) { + targetPosition = currentPosition; + } + } + + if (actor.getCurrentState().getClass().equals(PatrolState.class)){ + targetPosition = patrolPoints.get(actor.getPatrolPointIndex()); + } + + if (actor.getCurrentState().getClass().equals(WithdrawalState.class)){ + targetPosition = patrolPoints.get(actor.getPatrolPointIndex()); + } + + if (actor.getCurrentState().getClass().equals(FollowState.class)){ + targetPosition = actor.getFollowObject().getWorldPosition(); + } + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + if (targetPosition==null){ + DevLog.debugoutai(actor, "Charon", "AI State findnewpos", "Breakout2"); + return false; + } + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + /* + DevLog.debugoutai(actor, "Charon", "AI State findnewpos", "Breakout3"); + if (actor.getCurrentState().getClass().equals(RetreatState.class)){ + if(actor.getIntendedPrimaryAIState().equals(PatrolState.class)){ + actor.setCurrentState(new PatrolState()); + } + if(actor.getIntendedPrimaryAIState().equals(FollowState.class)){ + actor.setCurrentState(new FollowState()); + } + if(actor.getIntendedPrimaryAIState().equals(LoiterState.class)){ + actor.setCurrentState(new LoiterState()); + } + } + */ + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(movementPoints.size() != 0 && currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { + if(i == path.size() - 1 && movementPoints.size()>0){ + try { + movementPoints.remove(0); + } catch (ArrayIndexOutOfBoundsException ex){} // No idea why a vector with size>0 throws this sometimes + } + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + //float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float distance = NGECore.getInstance().aiService.distanceSquared(oldWorldPos, currentPathPosition.getWorldPosition()); // Ok to use, as distance is not directly used later + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + //float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + int fullong=0; // Approximation->faster + int halfshort=0; + float tempdx = dx; + float tempdz = dz; + if (tempdx<0) + tempdx*=-1; + if (tempdz<0) + tempdz*=-1; + if(tempdx > tempdz) { + fullong = (int)(tempdx*100); + halfshort = ((int)(tempdz*100)) >> 1; + } else { + fullong = (int)(tempdz*100); + halfshort = ((int)(tempdx*100)) >> 1; + } + float deltaDist = (fullong + halfshort)/100; + + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + + public boolean findNewLOSPosition(AIActor actor, float speed, float stopDistance, Point3D newPosition) { + speed *= 0.5; // 2 updates per second CreatureObject creature = actor.getCreature(); NGECore core = NGECore.getInstance(); @@ -94,6 +279,41 @@ public abstract class AIState { Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + if (targetPosition==null) + return false; + if (actor.getFollowObject()==null) + return false; + + int attempts = 0; + float LOSdistance = targetPosition.getWorldPosition().getDistance(actor.getFollowObject().getWorldPosition()); + Point3D LOSorigin = actor.getFollowObject().getWorldPosition(); + float deltaX = actor.getFollowObject().getWorldPosition().x-targetPosition.getWorldPosition().x; + float deltaZ = actor.getFollowObject().getWorldPosition().z-targetPosition.getWorldPosition().z; + float originAngle = (float) (Math.atan2(deltaX,deltaZ)); + int sign = 0; + while (!core.simulationService.checkLineOfSight(actor.getFollowObject(),targetPosition) && attempts<160){ + + float angle = 0; + if (sign==0){ + angle = originAngle + attempts; + sign = 1; + } else { + angle = originAngle - attempts; + sign = 0; + } + if (actor.getFollowObject() instanceof CreatureObject){ + if (((CreatureObject)actor.getFollowObject()).isPlayer()){ + System.out.println("CORRECTING LOS"); + } + } + + + targetPosition = new Point3D((float) (LOSorigin.x + LOSdistance * Math.cos(angle)), 0, (float) (LOSorigin.z + LOSdistance * Math.sin(angle))); + attempts++; + } + + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); if(distanceToTarget > stopDistance) { @@ -195,7 +415,7 @@ public abstract class AIState { float maxDistance = stopDistance; boolean finished = false; float dx, dz, newX = 0, newY = 0, newZ = 0; - @SuppressWarnings("unused") Vector movementPoints = actor.getMovementPoints(); + Vector movementPoints = actor.getMovementPoints(); CellObject cell = null; targetPosition = actor.getLoiterDestination(); @@ -421,8 +641,11 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getRunSpeed(); + if (creature.getAttachment("IsSlowVehicle")!=null){ + speed = (float) creature.getWalkSpeed(); + } float maxDistance = 6; if(creature.getWeaponId() != 0) { WeaponObject weapon = (WeaponObject) core.objectService.getObject(creature.getWeaponId()); @@ -439,7 +662,9 @@ public abstract class AIState { maxDistance = 1; Point3D newPosition = new Point3D(); - boolean foundNewPos = findNewPosition(actor, speed, maxDistance, newPosition); + + boolean foundNewPos = false; + foundNewPos = findNewPosition(actor, speed, maxDistance, newPosition); if(!foundNewPos || (newPosition.x == 0 && newPosition.z == 0)) return; @@ -454,20 +679,72 @@ public abstract class AIState { quaternion.w *= -1; } + core.simulationService.moveObject(creature, newPosition, quaternion, creature.getMovementCounter(), speed, newPosition.getCell()); + } + + public void doReposition(AIActor actor){ + + NGECore core = NGECore.getInstance(); + + CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14 || creature.getPosture() == 13) { + actor.setFollowObject(null); + return; + } + TangibleObject target = actor.getLastTarget(); + float speed = (float) creature.getRunSpeed(); + float maxDistance = 6; + if(creature.getWeaponId() != 0) { + WeaponObject weapon = (WeaponObject) core.objectService.getObject(creature.getWeaponId()); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } else if(creature.getSlottedObject("default_weapon") != null) { + WeaponObject weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } + Point3D currentPosition = creature.getWorldPosition(); + + if(target != null && !core.simulationService.checkLineOfSight(creature, target)) + maxDistance = 1; + + Point3D newPosition = actor.getRepositionLocation(); + + if(newPosition.x == 0 && newPosition.z == 0) + return; + + Point3D newWorldPos = newPosition.getWorldPosition(); + float direction = (float) Math.atan2(newWorldPos.x - currentPosition.x, newWorldPos.z - currentPosition.z); + if(direction < 0) + direction = (float) (2 * Math.PI + direction); + Quaternion quaternion = new Quaternion((float) Math.cos(direction / 2), 0, (float) Math.sin(direction / 2), 0); + if (quaternion.y < 0.0f && quaternion.w > 0.0f) { + quaternion.y *= -1; + quaternion.w *= -1; + } + core.simulationService.moveObject(creature, newPosition, quaternion, creature.getMovementCounter(), speed, newPosition.getCell()); } public void doPatrol(AIActor actor) { //NGECore.getInstance().aiService.logAI("AI STATE doPatrol"); + NGECore core = NGECore.getInstance(); CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14 || creature.getPosture() == 13) { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + + if (creature.isInCombat()){ + return; + } + + + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getWalkSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { @@ -481,24 +758,162 @@ public abstract class AIState { } Point3D currentPosition = creature.getWorldPosition(); - if(target != null && !core.simulationService.checkLineOfSight(creature, target)) - maxDistance = 1; +// if(target != null && !core.simulationService.checkLineOfSight(creature, target)) +// maxDistance = 1; // Manage Patrol points maxDistance = 1; + if (actor.getPatrolPoints().size()==0) + return; Point3D currentDestination = actor.getPatrolPoints().get(actor.getPatrolPointIndex()); - //System.out.println("currentPosition.getDistance2D(currentDestination)<1) " + currentPosition.getDistance2D(currentDestination)); - if (currentPosition.getDistance2D(currentDestination)<2){ + //System.out.println("currentPosition.getDistance2D(currentDestination) " + currentPosition.getDistance2D(currentDestination)); + if (NGECore.getInstance().aiService.distanceSquared2D(currentPosition, currentDestination)<4){ + //if (currentPosition.getDistance2D(currentDestination)<4){ if (actor.getPatrolPointIndex()=4 && NGECore.getInstance().invasionService.getInvasionPhase()!=3){ + actor.setAIactive(false); // switch off auto-target-recognition to counter lag + actor.setCurrentState(new IdleState()); + //System.out.println("AI switched off!"); + return; + } + + //actor.setCurrentState(new IdleState()); + // Wait state() Since this state does not require move,recover and all that its simple task + + //NGECore.getInstance().aiService.waitForEvent(actor, NGECore.getInstance().invasionService, "isDefendingGeneralAlive", false, WithdrawalState.class); + + return; // Last Patrol point reached and no loop + } } } Point3D newPosition = new Point3D(); boolean foundNewPos = findNewPosition(actor, speed, maxDistance, newPosition); - + + + + + if(!foundNewPos || (newPosition.x == 0 && newPosition.z == 0)) + return; + + Point3D newWorldPos = newPosition.getWorldPosition(); + float direction = (float) Math.atan2(newWorldPos.x - currentPosition.x, newWorldPos.z - currentPosition.z); + if(direction < 0) + direction = (float) (2 * Math.PI + direction); + Quaternion quaternion = new Quaternion((float) Math.cos(direction / 2), 0, (float) Math.sin(direction / 2), 0); + if (quaternion.y < 0.0f && quaternion.w > 0.0f) { + quaternion.y *= -1; + quaternion.w *= -1; + } + +// if (newPosition.getCell()==null) +// System.out.println("newPosition.getCell() is NULL"); + try{ + core.simulationService.moveObject(creature, newPosition, quaternion, creature.getMovementCounter(), speed, newPosition.getCell()); + } catch (NullPointerException e) { + // Just to identify what exactly is null here +// if (creature==null) +// System.out.print("creature==null" ); +// if (newPosition==null) +// System.out.print("newPosition==null" ); +// if (quaternion==null) +// System.out.print("quaternion==null" ); +// if (newPosition.getCell()==null) +// System.out.print("newPosition.getCell()==null" ); +// +// System.out.print("creature.getMovementCounter() " + creature.getMovementCounter()); + } + + } + + public void doWithdrawal(AIActor actor) { + //NGECore.getInstance().aiService.logAI("AI STATE doPatrol"); + + NGECore core = NGECore.getInstance(); + + if(actor==null) + return; + CreatureObject creature = actor.getCreature(); + if(creature==null) + return; + +// if (creature.getPlanet().getName().equals("talus") && creature.getTemplate().contains("stormtrooper")){ +// System.out.println("actor " + actor.getActorID() + " stateID " + stateID + " creatureID"+ creature.getObjectID()+ " TIMEDIFF: " + (System.currentTimeMillis()-lastExecutionTime)); +// lastExecutionTime = System.currentTimeMillis(); +// } + if(creature.getPosture() == 14 || creature.getPosture() == 13) { + actor.setFollowObject(null); + return; + } + +// if (creature.isInCombat()){ +// return; +// } + + + TangibleObject target = actor.getFollowObject(); + float speed = (float) creature.getWalkSpeed(); + float maxDistance = 6; + if(creature.getWeaponId() != 0) { + WeaponObject weapon = (WeaponObject) core.objectService.getObject(creature.getWeaponId()); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } else if(creature.getSlottedObject("default_weapon") != null) { + WeaponObject weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } + Point3D currentPosition = creature.getWorldPosition(); + +// if(target != null && !core.simulationService.checkLineOfSight(creature, target)) +// maxDistance = 1; + + // Manage Patrol points + maxDistance = 1; + if (actor.getPatrolPoints().size()==0) + return; + if (actor.getPatrolPointIndex()<=0) + actor.setPatrolPointIndex(0); + Point3D currentDestination = actor.getPatrolPoints().get(actor.getPatrolPointIndex()); + //System.out.println("currentPosition.getDistance2D(currentDestination) " + currentPosition.getDistance2D(currentDestination)); + if (NGECore.getInstance().aiService.distanceSquared2D(currentPosition, currentDestination)<4){ + //if (currentPosition.getDistance2D(currentDestination)<4){ + if (actor.getPatrolPointIndex()>0){ + actor.setPatrolPointIndex(actor.getPatrolPointIndex()-1); + } else { + if (actor!=null) + actor.destroyActor(); + if (creature!=null){ + core.simulationService.remove(creature, creature.getWorldPosition().x, creature.getWorldPosition().z, true); // Make sure + core.objectService.destroyObject(creature.getObjectID()); + } + return; // First Patrol point reached + } + } + + Point3D newPosition = new Point3D(); + boolean foundNewPos = findNewPosition(actor, speed, maxDistance, newPosition); + + + + if(!foundNewPos || (newPosition.x == 0 && newPosition.z == 0)) return; @@ -541,7 +956,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getWalkSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { @@ -654,7 +1069,6 @@ public abstract class AIState { } - @SuppressWarnings("unused") public void doFollow(AIActor actor) { //NGECore.getInstance().aiService.logAI("AI STATE doPatrol"); NGECore core = NGECore.getInstance(); @@ -664,7 +1078,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getRunSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { diff --git a/src/services/ai/states/AttackState.java b/src/services/ai/states/AttackState.java index 98dc5b7c..203b490b 100644 --- a/src/services/ai/states/AttackState.java +++ b/src/services/ai/states/AttackState.java @@ -24,8 +24,10 @@ package services.ai.states; import java.util.Random; import java.util.Vector; +import engine.resources.scene.Point3D; import main.NGECore; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; import services.ai.AIActor; import tools.DevLog; @@ -34,12 +36,20 @@ public class AttackState extends AIState { @Override public byte onEnter(AIActor actor) { - DevLog.debugout("Charon", "AI Attack State", "onEnter"); + DevLog.debugoutai(actor, "Charon", "AI Attack State", "onEnter"); + CreatureObject creature = actor.getCreature(); + if (creature == null || actor==null) + return StateResult.DEAD; + DevLog.debugoutai(actor, "Charon", "AI Attack State", "creature.isInCombat() " + creature.isInCombat()); + DevLog.debugoutai(actor, "Charon", "AI Attack State", "creature.getDefendersList().size() == 0 " + (creature.getDefendersList().size() == 0)); + DevLog.debugoutai(actor, "Charon", "AI Attack State", "actor.getFollowObject() == null " + (actor.getFollowObject() == null)); if(creature.getPosture() == 14) return StateResult.DEAD; if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) return StateResult.FINISHED; + creature.setLookAtTarget(actor.getFollowObject().getObjectID()); + creature.setIntendedTarget(actor.getFollowObject().getObjectID()); actor.scheduleMovement(); actor.scheduleRecovery(); return StateResult.UNFINISHED; @@ -52,22 +62,35 @@ public class AttackState extends AIState { actor.getCreature().setLookAtTarget(0); actor.getCreature().setIntendedTarget(0); actor.setFollowObject(null); - DevLog.debugout("Charon", "AI Attack State", "onExit"); + DevLog.debugoutai(actor, "Charon", "AI Attack State", "onExit"); return StateResult.FINISHED; } @Override public byte move(AIActor actor) { CreatureObject creature = actor.getCreature(); + if (creature==null) + return StateResult.FINISHED; + if(creature.getPosture() == 14) return StateResult.DEAD; actor.getMovementPoints().clear(); if(actor.getFollowObject() != null) { - if(actor.getSpawnPosition().getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), actor.getFollowObject().getWorldPosition())) { - actor.removeDefender(actor.getFollowObject()); - //actor.scheduleMovement(); - return StateResult.UNFINISHED; - } + Point3D checkPosition = actor.getSpawnPosition().getWorldPosition(); // IdleState default + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + checkPosition = creature.getWorldPosition(); + if (actor.getIntendedPrimaryAIState().getClass().equals(FollowState.class)) + checkPosition = creature.getWorldPosition(); + + try { + if(checkPosition.getDistance(creature.getWorldPosition()) > 128 || NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), actor.getFollowObject().getWorldPosition())) { + actor.removeDefender(actor.getFollowObject()); + //actor.scheduleMovement(); + //return StateResult.UNFINISHED; + return StateResult.FINISHED; + } + } catch (Exception ex){} // When the followobject turns becomes null inside the if scope an npe can occur + float maxDistance = 0; if(creature.getWeaponId() != 0) { WeaponObject weapon = (WeaponObject) NGECore.getInstance().objectService.getObject(creature.getWeaponId()); @@ -79,19 +102,24 @@ public class AttackState extends AIState { maxDistance = weapon.getMaxRange() - 1; } try{ - if(actor.getFollowObject().getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) + if(actor.getFollowObject().getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance){ actor.setNextPosition(actor.getFollowObject().getPosition()); - else { + // find los pos + } else { //recover(actor); actor.faceObject(actor.getFollowObject()); actor.scheduleMovement(); return StateResult.UNFINISHED; } } catch (Exception e){ - DevLog.debugout("Charon", "AI Attack State Exception move method", "actor " + actor); - DevLog.debugout("Charon", "AI Attack State Exception move method", "actor.getFollowObject() " + actor.getFollowObject()); - DevLog.debugout("Charon", "AI Attack State Exception move method", "actor.getFollowObject().getWorldPosition() " + actor.getFollowObject().getWorldPosition()); - DevLog.debugout("Charon", "AI Attack State Exception move method", "creature.getWorldPosition() " + creature.getWorldPosition()); + if (actor!=null) + DevLog.debugoutai(actor, "Charon", "AI Attack State Exception move method", "actor " + actor); + if (actor.getFollowObject()!=null) + DevLog.debugoutai(actor, "Charon", "AI Attack State Exception move method", "actor.getFollowObject() " + actor.getFollowObject()); + if (actor.getFollowObject()!=null) + DevLog.debugoutai(actor, "Charon", "AI Attack State Exception move method", "actor.getFollowObject().getWorldPosition() " + actor.getFollowObject().getWorldPosition()); + if (creature!=null) + DevLog.debugoutai(actor, "Charon", "AI Attack State Exception move method", "creature.getWorldPosition() " + creature.getWorldPosition()); } } @@ -105,6 +133,7 @@ public class AttackState extends AIState { @Override public byte recover(AIActor actor) { CreatureObject creature = actor.getCreature(); + DevLog.debugoutai(actor, "Charon", "AI Attack Recover State", creature.getTemplate()); float maxDistance = 0; WeaponObject weapon = null; if(creature.getWeaponId() != 0) { @@ -119,55 +148,102 @@ public class AttackState extends AIState { if(weapon == null) return StateResult.FINISHED; if(actor.getTimeSinceLastAttack() < weapon.getAttackSpeed() * 1000) { - //actor.scheduleRecovery(); + actor.scheduleRecovery(); return StateResult.UNFINISHED; } NGECore core = NGECore.getInstance(); if(creature.getPosture() == 14) return StateResult.DEAD; - if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) - { - if (creature.getLookAtTarget() != 0) - creature.setLookAtTarget(0); - if (creature.getIntendedTarget() != 0) - creature.setIntendedTarget(0); - actor.setFollowObject(null); - actor.setCurrentState(new RetreatState()); - return StateResult.FINISHED; - } - CreatureObject target = actor.getFollowObject(); + + + TangibleObject target = actor.getFollowObject(); if(target != actor.getHighestDamageDealer() && actor.getHighestDamageDealer() != null) { actor.setFollowObject(actor.getHighestDamageDealer()); target = actor.getFollowObject(); } if(target == null) { - DevLog.debugout("Charon", "AI Attack State", "null target"); + DevLog.debugoutai(actor, "Charon", "AI Attack State", "null target"); actor.scheduleRecovery(); return StateResult.UNFINISHED; } - if(target.getPosture() == 13 || target.getPosture() == 14 || target.isInStealth()) { - - actor.setFollowObject(actor.getHighestDamageDealer()); - target = actor.getFollowObject(); - if(target == null) - { - if (creature.getLookAtTarget() != 0) - creature.setLookAtTarget(0); - if (creature.getIntendedTarget() != 0) - creature.setIntendedTarget(0); - - } - actor.setFollowObject(null); - actor.removeDefender(target); - - actor.setCurrentState(new RetreatState()); + + // If AI has no LOS to target, reposition it + if (!core.simulationService.checkLineOfSight(target,creature)){ + actor.setLastTarget(target); + actor.setCurrentState(new RepositionState()); return StateResult.FINISHED; } - if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || target.getPosture() == 13 || target.getPosture() == 14) { - actor.removeDefender(target); - actor.scheduleRecovery(); - return StateResult.UNFINISHED; + + + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + { + +// System.out.println("creature.isInCombat() " + creature.isInCombat()); +// System.out.println("creature.getDefendersList().size() " + creature.getDefendersList().size()); +// System.out.println("actor.getFollowObject() " + actor.getFollowObject()); + creature.setLookAtTarget(0); + creature.setIntendedTarget(0); + actor.setFollowObject(null); + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; } + + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject) target; + if(targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14 || targetCreature.isInStealth()) { + + actor.setFollowObject(actor.getHighestDamageDealer()); + target = (CreatureObject) actor.getFollowObject(); + if(target == null) + { + creature.setLookAtTarget(0); + creature.setIntendedTarget(0); + + } + actor.setFollowObject(null); + actor.removeDefender(target); + + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; + } + if(targetCreature.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14) { + actor.removeDefender(target); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + } else { + TangibleObject targetObject = (TangibleObject) target; + if((targetObject.getConditionDamage()>=targetObject.getMaximumCondition())) { + + actor.setFollowObject(actor.getHighestDamageDealer()); + target = (CreatureObject) actor.getFollowObject(); + if(target == null) + { + creature.setLookAtTarget(0); + creature.setIntendedTarget(0); + + } + actor.setFollowObject(null); + actor.removeDefender(target); + + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; + } + } + if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) { actor.scheduleRecovery(); return StateResult.UNFINISHED; @@ -179,17 +255,18 @@ public class AttackState extends AIState { // Pet // if (creature.getOwnerId()>0) // attacks = creature.getSpecialAttacks(); - if (creature.getLookAtTarget() != target.getObjectId()) - creature.setLookAtTarget(target.getObjectId()); - if (creature.getIntendedTarget() != target.getObjectId()) - creature.setIntendedTarget(target.getObjectId()); - if(attacks.size() == 0) { + creature.setLookAtTarget(target.getObjectId()); + creature.setIntendedTarget(target.getObjectId()); + + if (attacks==null) { + //if(attacks.size() == 0) { core.commandService.callCommand(creature, actor.getMobileTemplate().getDefaultAttack(), target, ""); } else { Random rand = new Random(); if(rand.nextFloat() <= 0.33f) { - core.commandService.callCommand(creature, attacks.get(rand.nextInt(attacks.size())), target, ""); + if(attacks.size() > 0) + core.commandService.callCommand(creature, attacks.get(rand.nextInt(attacks.size())), target, ""); } else { core.commandService.callCommand(creature, actor.getMobileTemplate().getDefaultAttack(), target, ""); } diff --git a/src/services/ai/states/DeathState.java b/src/services/ai/states/DeathState.java index ed38449f..bb49a07e 100644 --- a/src/services/ai/states/DeathState.java +++ b/src/services/ai/states/DeathState.java @@ -33,16 +33,20 @@ public class DeathState extends AIState { public byte onEnter(AIActor actor) { NGECore.getInstance().aiService.awardExperience(actor); NGECore.getInstance().aiService.awardGcw(actor); + actor.setActorAlive(false); actor.getCreature().setAttachment("radial_filename", "npc/corpse"); //NGECore.getInstance().scriptService.callScript("scripts/radial/npc/corpse", "", "createRadial", NGECore.getInstance(), actor.getCreature().getKiller(), actor.getCreature(), new Vector()); actor.scheduleDespawn(); - CreatureObject killer = (CreatureObject)actor.getCreature().getKiller(); - if (killer==null) - killer = actor.getHighestDamageDealer(); - actor.getCreature().setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); - NGECore.getInstance().lootService.DropLoot(killer,(TangibleObject)(actor.getCreature())); - actor.destroyActor(); // to prevent standing up right after death + if (actor.getCreature().getKiller() instanceof CreatureObject){ + CreatureObject killer = (CreatureObject)actor.getCreature().getKiller(); + if (killer==null) + killer = actor.getHighestDamageDealer(); + actor.getCreature().setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + if (killer.isPlayer()) // No point to do this for NPCs + NGECore.getInstance().lootService.DropLoot(killer,(TangibleObject)(actor.getCreature())); + } + //actor.destroyActor(); // to prevent standing up right after death return 0; } diff --git a/src/services/ai/states/PatrolState.java b/src/services/ai/states/PatrolState.java index 2a571391..72cb9b27 100644 --- a/src/services/ai/states/PatrolState.java +++ b/src/services/ai/states/PatrolState.java @@ -21,16 +21,22 @@ ******************************************************************************/ package services.ai.states; -import main.NGECore; import resources.objects.creature.CreatureObject; import services.ai.AIActor; +import tools.DevLog; public class PatrolState extends AIState { - + + private boolean locked = false; + + public PatrolState(){ + stateID = autoStateID++; + } + @Override public byte onEnter(AIActor actor) { - // TODO Auto-generated method stub - NGECore.getInstance().aiService.logAI("PATROL ENTERED!"); + + DevLog.debugoutai(actor, "Charon", "AI PatrolState", "PATROL ENTERED!"); CreatureObject creature = actor.getCreature(); if(creature.getPosture() == 14) return StateResult.DEAD; @@ -41,27 +47,37 @@ public class PatrolState extends AIState { @Override public byte onExit(AIActor actor) { - // TODO Auto-generated method stub - NGECore.getInstance().aiService.logAI("EXITING PATROL STATE"); + DevLog.debugoutai(actor, "Charon", "AI PatrolState", "EXITING PATROL STATE!"); actor.setLastPositionBeforeStateChange(actor.getCreature().getWorldPosition()); - return 0; + locked = true; + return StateResult.FINISHED; } @Override public byte move(AIActor actor) { - // TODO Auto-generated method stub - //System.out.println("move in patrolState"); + DevLog.debugoutai(actor, "Charon", "AI PatrolState", "PATROL MOVE!"); + if (locked){ + System.out.println("PatrolState locked!"); + return StateResult.FINISHED; + } + CreatureObject creature = actor.getCreature(); + if(creature.isInCombat()){ + //System.out.println("PatrolState locking!"); + locked = true; + return StateResult.FINISHED; + } doPatrol(actor); -// if (actor.getCreature().getPlanet().getName().equals("dathomir")) -// NGECore.getInstance().aiService.logAI("WalkingSpeed " + actor.getCreature().getWalkSpeed()); actor.scheduleMovement(); return StateResult.UNFINISHED; } @Override public byte recover(AIActor actor) { - // TODO Auto-generated method stub - return 0; + if (actor.getFollowObject()!=null) + System.out.println("recover follow object is not null"); + if (actor.getFollowObject()!=null) + System.out.println("recover follow object is not null"); + return StateResult.UNFINISHED; } } diff --git a/src/services/ai/states/RepositionState.java b/src/services/ai/states/RepositionState.java new file mode 100644 index 00000000..f2452abc --- /dev/null +++ b/src/services/ai/states/RepositionState.java @@ -0,0 +1,163 @@ +package services.ai.states; + +import main.NGECore; +import engine.resources.scene.Point3D; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import services.ai.AIActor; +import tools.DevLog; + +/** + * @author Charon + */ + +public class RepositionState extends AIState{ + + int prog = 10; + + @Override + public byte onEnter(AIActor actor) { + DevLog.debugoutai(actor, "Charon", "AI RepositionState", "onEnter"); + CreatureObject creature = actor.getCreature(); + Point3D creaturePosition = creature.getWorldPosition(); + + TangibleObject target = actor.getLastTarget(); +// Point3D LOSorigin = targetPosition; +// float deltaX = LOSorigin.x-creaturePosition.x; +// float deltaZ = LOSorigin.z-creaturePosition.z; +// float originAngle = (float) (Math.atan2(deltaX,deltaZ)); + Point3D scanPosition = creaturePosition; + TangibleObject tempObject = new TangibleObject(); // LOS overload for pos and creature does not work correctly + tempObject.setPosition(scanPosition); + boolean breakout = false; + boolean foundPos = false; + actor.setProgressionMarker(1); + long repositionCalculationStart = System.currentTimeMillis(); // Limit time this is calculated to prevent deadloops + while (!NGECore.getInstance().simulationService.checkLineOfSight(target,scanPosition) && !breakout || System.currentTimeMillis()>repositionCalculationStart+2000){ + // Quick, light-weight way to get the AI into a firing LOS position + // ToDo: Check if the Quadnode at the LOS position contains a structure + // Required: Add according method to Quadtree.java + + boolean abortCondition = false; + for (int x=1;x<50 && !abortCondition;x=x+1){ + if (NGECore.getInstance().simulationService.checkLineOfSight(target,new Point3D(creaturePosition.x+x,creaturePosition.y,creaturePosition.z)) && !NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), creaturePosition.x+x, creaturePosition.z)){ + scanPosition = new Point3D(creaturePosition.x+x,creaturePosition.y,creaturePosition.z); + abortCondition = true; + } + } + for (int x=-1;x>-50 && !abortCondition;x=x-1){ + if (NGECore.getInstance().simulationService.checkLineOfSight(target,new Point3D(creaturePosition.x+x,creaturePosition.y,creaturePosition.z)) && !NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), creaturePosition.x+x, creaturePosition.z)){ + scanPosition = new Point3D(creaturePosition.x+x,creaturePosition.y,creaturePosition.z); + abortCondition = true; + } + } + for (int z=1;z<50 && !abortCondition;z=z+1){ + if (NGECore.getInstance().simulationService.checkLineOfSight(target,new Point3D(creaturePosition.x,creaturePosition.y,creaturePosition.z+z)) && !NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), creaturePosition.x, creaturePosition.z+z)){ + scanPosition = new Point3D(creaturePosition.x,creaturePosition.y,creaturePosition.z+z); + abortCondition = true; + } + } + for (int z=-1;z>-50 && !abortCondition;z=z-1){ + if (NGECore.getInstance().simulationService.checkLineOfSight(target,new Point3D(creaturePosition.x,creaturePosition.y,creaturePosition.z+z)) && !NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), creaturePosition.x, creaturePosition.z+z)){ + scanPosition = new Point3D(creaturePosition.x,creaturePosition.y,creaturePosition.z+z); + abortCondition = true; + } + } + actor.setProgressionMarker(2); + + if (!NGECore.getInstance().simulationService.checkLineOfSight(target,scanPosition)){ + foundPos=true; + } + +// else +// System.out.println("LOS found"); +// + breakout=true; + } + actor.setProgressionMarker(3); + if (foundPos){ + actor.setRepositionLocation(scanPosition); + actor.setRepositionStartTime(System.currentTimeMillis()); + } else { + float positionY = NGECore.getInstance().terrainService.getHeight(target.getPlanetId(), target.getPosition().x, target.getPosition().z); + actor.setRepositionLocation(new Point3D(target.getWorldPosition().x,positionY,target.getWorldPosition().z)); + actor.setRepositionStartTime(System.currentTimeMillis()+5000); // give it more time + } + + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(AIActor actor) { + // TODO Auto-generated method stub + actor.setProgressionMarker(9); + TangibleObject followObject = actor.getFollowObject(); + if (followObject==null) + return StateResult.FINISHED; + + if (followObject instanceof CreatureObject) + if (((CreatureObject) followObject).getPosture()==14 || ((CreatureObject) followObject).getPosture()==13) + actor.setFollowObject(null); + + if (! (followObject instanceof CreatureObject)) + if(followObject.getConditionDamage()>=followObject.getMaximumCondition()) + actor.setFollowObject(null); + + DevLog.debugoutai(actor, "Charon", "AI RepositionState", "exit"); + + return StateResult.FINISHED; + } + + @Override + public byte move(AIActor actor) { + DevLog.debugoutai(actor, "Charon", "AI RepositionState", "move"); + actor.setProgressionMarker(prog++); + Point3D newPosition = actor.getRepositionLocation(); + TangibleObject target = actor.getLastTarget(); + if (target==null){ + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; + } + + if (target instanceof CreatureObject) + if (((CreatureObject) target).getPosture()==14 || ((CreatureObject) target).getPosture()==13){ + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; + } + + if (! (target instanceof CreatureObject)) + if(target.getConditionDamage()>=target.getMaximumCondition()){ + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new RetreatState()); + else { + actor.setCurrentState(new RetreatState()); + } + return StateResult.FINISHED; + } + + if (newPosition.getDistance2D(target.getWorldPosition())<0.5 || System.currentTimeMillis()>actor.getRepositionStartTime()+5000){ + actor.addDefender(target); + actor.setCurrentState(new AttackState()); + return StateResult.FINISHED; + } + + doReposition(actor); + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + + @Override + public byte recover(AIActor actor) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/src/services/ai/states/RetreatState.java b/src/services/ai/states/RetreatState.java index b94684fe..f2515724 100644 --- a/src/services/ai/states/RetreatState.java +++ b/src/services/ai/states/RetreatState.java @@ -25,9 +25,13 @@ import main.NGECore; import engine.resources.scene.Point3D; import resources.objects.creature.CreatureObject; import services.ai.AIActor; +import tools.DevLog; public class RetreatState extends AIState { - + + private long retreatStartTime = 0L; + private Point3D retreatStartPos = null; + @Override public byte onEnter(AIActor actor) { /*synchronized(actor.getDamageMap()) { @@ -35,8 +39,11 @@ public class RetreatState extends AIState { actor.removeDefender(defender); } }*/ - NGECore.getInstance().aiService.logAI("RetreatState ENTER "); - + DevLog.debugoutai(actor, "Charon", "AI RetreatState", "RetreatState ENTER!"); + CreatureObject creature = actor.getCreature(); + if (creature.getPosture()==13 || creature.getPosture()==14) + return StateResult.FINISHED; + creature.setInCombat(false); if (actor.getCreature().getOwnerId()>0){ CreatureObject owner = (CreatureObject) NGECore.getInstance().objectService.getObject(actor.getCreature().getOwnerId()); actor.setFollowObject(owner); @@ -44,6 +51,9 @@ public class RetreatState extends AIState { return StateResult.FINISHED; } else actor.setFollowObject(null); + + retreatStartTime = System.currentTimeMillis(); + retreatStartPos = creature.getWorldPosition(); actor.scheduleMovement(); return StateResult.UNFINISHED; } @@ -52,16 +62,20 @@ public class RetreatState extends AIState { public byte onExit(AIActor actor) { // TODO Auto-generated method stub //actor.setCurrentState(actor.getIntendedPrimaryAIState()); + DevLog.debugoutai(actor, "Charon", "AI RetreatState", "RetreatState EXIT!"); return StateResult.FINISHED; } @Override public byte move(AIActor actor) { - + DevLog.debugoutai(actor, "Charon", "AI RetreatState", "RetreatState MOVE!"); Point3D retreatPosition = actor.getSpawnPosition(); if (actor.getIntendedPrimaryAIState() instanceof PatrolState) retreatPosition = actor.getLastPositionBeforeStateChange(); + CreatureObject creature = actor.getCreature(); + if (creature.getPosture()==13 || creature.getPosture()==14) + return StateResult.FINISHED; actor.setNextPosition(retreatPosition); actor.getMovementPoints().clear(); actor.getMovementPoints().add(retreatPosition); @@ -71,19 +85,49 @@ public class RetreatState extends AIState { return StateResult.FOLLOW; if(actor.getCreature().getWorldPosition().getDistance(retreatPosition) > 5) { - //NGECore.getInstance().aiService.logAI("RetreatState ENTER move if case dist " + actor.getCreature().getWorldPosition().getDistance(retreatPosition)); actor.scheduleMovement(); } else { - //NGECore.getInstance().aiService.logAI("RetreatState ENTER move else case"); + if (actor.getIntendedPrimaryAIState().getClass().equals(IdleState.class)) - return StateResult.IDLE; + actor.setCurrentState(new IdleState()); if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) - return StateResult.PATROL; + actor.setCurrentState(new PatrolState()); if (actor.getIntendedPrimaryAIState().getClass().equals(LoiterState.class)) - return StateResult.LOITER; + actor.setCurrentState(new LoiterState()); if (actor.getIntendedPrimaryAIState().getClass().equals(FollowState.class)) - return StateResult.FOLLOW; + actor.setCurrentState(new FollowState()); + + return StateResult.FINISHED; } + + if(System.currentTimeMillis()> retreatStartTime + 5000 && creature.getWorldPosition().getDistance2D(retreatStartPos)<1.5){ + // Actor is locked in retreat state, get back to intended state + if (actor.getIntendedPrimaryAIState().getClass().equals(IdleState.class)) + actor.setCurrentState(new IdleState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new PatrolState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(LoiterState.class)) + actor.setCurrentState(new LoiterState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(FollowState.class)) + actor.setCurrentState(new FollowState()); + + return StateResult.FINISHED; + } + + if(System.currentTimeMillis()> retreatStartTime + 40000){ + // Actor is locked in retreat state, get back to intended state after 40s, no matter what + if (actor.getIntendedPrimaryAIState().getClass().equals(IdleState.class)) + actor.setCurrentState(new IdleState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(PatrolState.class)) + actor.setCurrentState(new PatrolState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(LoiterState.class)) + actor.setCurrentState(new LoiterState()); + if (actor.getIntendedPrimaryAIState().getClass().equals(FollowState.class)) + actor.setCurrentState(new FollowState()); + + return StateResult.FINISHED; + } + return StateResult.UNFINISHED; } diff --git a/src/services/ai/states/TurretAIState.java b/src/services/ai/states/TurretAIState.java new file mode 100644 index 00000000..2c6e89c7 --- /dev/null +++ b/src/services/ai/states/TurretAIState.java @@ -0,0 +1,415 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import java.util.NoSuchElementException; +import java.util.Vector; +import main.NGECore; +import engine.resources.scene.Point3D; +import resources.objects.cell.CellObject; +import resources.objects.tangible.TangibleObject; +import services.ai.TurretAIActor; + +public abstract class TurretAIState { + + public abstract byte onEnter(TurretAIActor actor) throws Exception; + public abstract byte onExit(TurretAIActor actor) throws Exception; + public abstract byte move(TurretAIActor actor) throws Exception; + public abstract byte recover(TurretAIActor actor) throws Exception; + + public enum StateResult {; + + // default error state result + public static final byte NONE = 0; + // finished with state + public static final byte FINISHED = 1; + // unfinished with state, call recover() + public static final byte UNFINISHED = 2; + public static final byte DEAD = 3; + // for deaggro or idling + public static final byte IDLE = 4; + public static final byte PATROL = 5; + public static final byte LOITER = 6; + public static final byte FOLLOW = 7; + + } + + public boolean findNewPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + //Vector patrolPoints = actor.getPatrolPoints(); + CellObject cell = null; + //while(!finished && movementPoints.size() != 0) { + + + + if (movementPoints.size() != 0){ + try{ + targetPosition = movementPoints.firstElement(); + } catch (NoSuchElementException e) { + targetPosition = currentPosition; + } + } + + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(movementPoints.size() != 0 && currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { + if(i == path.size() - 1) + movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + + public boolean findNewLoiterPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + //Vector movementPoints = actor.getMovementPoints(); + CellObject cell = null; + + targetPosition = actor.getLoiterDestination(); + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { +// if(i == path.size() - 1) +// movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + public boolean findNewFollowPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + Vector patrolPoints = actor.getPatrolPoints(); + CellObject cell = null; + //while(!finished && movementPoints.size() != 0) { + + + if (movementPoints.size() != 0) + targetPosition = movementPoints.firstElement(); + + if (actor.getCurrentState().getClass().equals(PatrolState.class)){ + targetPosition = patrolPoints.get(actor.getPatrolPointIndex()); + } + + if (actor.getCurrentState().getClass().equals(FollowState.class)){ + targetPosition = actor.getFollowObject().getWorldPosition(); + } + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(movementPoints.size() != 0 && currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { + if(i == path.size() - 1) + movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + public void doMove(TurretAIActor actor) { + + } + + public void doPatrol(TurretAIActor actor) { + + } + + public void doLoiter(TurretAIActor actor) { + + } + + public void doFollow(TurretAIActor actor) { + + } + +} diff --git a/src/services/ai/states/TurretAttackState.java b/src/services/ai/states/TurretAttackState.java new file mode 100644 index 00000000..29ac49ca --- /dev/null +++ b/src/services/ai/states/TurretAttackState.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import main.NGECore; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.TurretAIActor; +import tools.DevLog; + +public class TurretAttackState extends TurretAIState { + + @Override + public byte onEnter(TurretAIActor actor) { + DevLog.debugoutai(actor, "Charon", "Turret AI Attack State", "onEnter"); + TangibleObject creature = actor.getCreature(); + +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getConditionDamage() " + creature.getConditionDamage()); +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getMaximumCondition() " + creature.getMaximumCondition()); + + if(creature.getConditionDamage()>=creature.getMaximumCondition()){ + return StateResult.DEAD; + } + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + return StateResult.FINISHED; + +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getDefendersList().size() " + creature.getDefendersList().size()); +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter actor.getFollowObject() " + actor.getFollowObject()); + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + return StateResult.FINISHED; + + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(TurretAIActor actor) { + // TODO Auto-generated method stub + DevLog.debugoutai(actor, "Charon", "Turret AI Attack State", "onExit"); + + TangibleObject creature = actor.getCreature(); + creature.setInCombat(false); +// actor.getCreature().setLookAtTarget(0); +// actor.getCreature().setIntendedTarget(0); + actor.setFollowObject(null); +// DevLog.debugout("Charon", "AI Attack State", "onExit"); + return StateResult.FINISHED; + } + + @Override + public byte move(TurretAIActor actor) { + + return StateResult.FINISHED; + + } + + @Override + public byte recover(TurretAIActor actor) { + DevLog.debugoutai(actor, "Charon", "TurretAI Attack State", "recover "); + TangibleObject creature = actor.getCreature(); + if (creature==null) + return StateResult.FINISHED; + + float maxDistance = 0; + WeaponObject weapon = null; + //weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + + long weaponID = (long) creature.getAttachment("TurretWeapon"); + weapon = (WeaponObject) NGECore.getInstance().objectService.getObject(weaponID); + //DevLog.debugout("Charon", "AI Attack State", "weapontype " + weapon.getTemplate()); + if(weapon == null) + return StateResult.FINISHED; + + + maxDistance = weapon.getMaxRange() - 1; + + + // Here is place for turret cooldown + if(actor.getTimeSinceLastAttack() < weapon.getAttackSpeed() * 1000) { + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + NGECore core = NGECore.getInstance(); + + if (core.aiService.getCheckAI()!=null){ +// if (core.aiService.getCheckAI().getObjectID()==creature.getObjectID()) +// System.out.println("creature.getConditionDamage() " + creature.getConditionDamage() + " creature.getMaximumCondition() " + creature.getMaximumCondition()); + } + + if(creature.getConditionDamage()>=creature.getMaximumCondition()){ +// String effectFile = "clienteffect/npe_explosion_02.cef"; +// Vector allPlayers = core.simulationService.getAllNearPlayers(300, creature.getPlanet(), creature.getPosition()); +// for (CreatureObject player : allPlayers){ +// PlayClientEffectLocMessage cEffMsg = new PlayClientEffectLocMessage(effectFile, creature.getPlanet().getName(), creature.getPosition()); +// player.getClient().getSession().write(cEffMsg.serialize()); +// } + return StateResult.DEAD; + } + + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + { +// creature.setLookAtTarget(0); +// creature.setIntendedTarget(0); + actor.setFollowObject(null); + actor.setCurrentState(new TurretIdleState()); + return StateResult.FINISHED; + } + + TangibleObject target = actor.getFollowObject(); + if(target != actor.getHighestDamageDealer() && actor.getHighestDamageDealer() != null) { + actor.setFollowObject(actor.getHighestDamageDealer()); + target = actor.getFollowObject(); + } + if(target == null) { + DevLog.debugoutai(actor, "Charon", "AI Attack State", "null target"); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject) target; + if(targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14 || targetCreature.isInStealth()) { + + actor.setFollowObject(actor.getHighestDamageDealer()); + target = (CreatureObject) actor.getFollowObject(); + if(target == null) + { +// creature.setLookAtTarget(0); //Is only accessible from CreatureObject, not TANO +// creature.setIntendedTarget(0); + + } + actor.setFollowObject(null); + actor.removeDefender(target); + + actor.setCurrentState(new TurretIdleState()); + return StateResult.FINISHED; + } + if(targetCreature.getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance || targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14) { + actor.removeDefender(target); +// actor.scheduleRecovery(); +// return StateResult.UNFINISHED; +// String effectFile = "clienteffect/npe_explosion_02.cef"; +// Vector allPlayers = core.simulationService.getAllNearPlayers(300, creature.getPlanet(), creature.getPosition()); +// for (CreatureObject player : allPlayers){ +// PlayClientEffectLocMessage cEffMsg = new PlayClientEffectLocMessage(effectFile, creature.getPlanet().getName(), creature.getPosition()); +// player.getClient().getSession().write(cEffMsg.serialize()); +// } + return StateResult.FINISHED; + } + } + +// DevLog.debugout("Charon", "AI Attack State", "prior to attacks dist " + target.getWorldPosition().getDistance(creature.getWorldPosition())); +// DevLog.debugout("Charon", "AI Attack State", "prior to attacks maxDistance " + maxDistance); + + if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) { + actor.removeDefender(target); +// actor.scheduleRecovery(); +// return StateResult.UNFINISHED; + + return StateResult.FINISHED; + } + //actor.faceObject(target); + core.commandService.callCommand(creature, "rangedShot", target, ""); + + actor.setLastAttackTimestamp(System.currentTimeMillis()); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + +} diff --git a/src/services/ai/states/TurretIdleState.java b/src/services/ai/states/TurretIdleState.java new file mode 100644 index 00000000..e6543a66 --- /dev/null +++ b/src/services/ai/states/TurretIdleState.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import services.ai.TurretAIActor; +import tools.DevLog; + +public class TurretIdleState extends TurretAIState { + + @Override + public byte onEnter(TurretAIActor actor) { + // TODO Auto-generated method stub + DevLog.debugoutai(actor,"Charon", "Turret AI Idle State", "onEnter"); + //return 0; + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(TurretAIActor actor) { + // TODO Auto-generated method stub + DevLog.debugoutai(actor,"Charon", "Turret AI Idle State", "onExit"); + //return 0; + return StateResult.FINISHED; + } + + @Override + public byte move(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public byte recover(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/services/ai/states/WithdrawalState.java b/src/services/ai/states/WithdrawalState.java new file mode 100644 index 00000000..2f343107 --- /dev/null +++ b/src/services/ai/states/WithdrawalState.java @@ -0,0 +1,66 @@ +package services.ai.states; + +import resources.datatables.Options; +import resources.objects.creature.CreatureObject; +import services.ai.AIActor; +import tools.DevLog; + +public class WithdrawalState extends AIState { +private boolean locked = false; + + + @Override + public byte onEnter(AIActor actor) { + + DevLog.debugoutai(actor, "Charon", "AI WithdrawalState", "WITHDRAWAL ENTERED!"); + CreatureObject creature = actor.getCreature(); + if (creature==null) + return 0; + creature.setOptions(Options.INVULNERABLE, true); + if(creature.getPosture() == 14) + return StateResult.DEAD; + actor.setPatrolPointIndex(actor.getPatrolPointIndex()-1); + actor.scheduleMovement(); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(AIActor actor) { + DevLog.debugoutai(actor, "Charon", "AI WithdrawalState", "EXITING WITHDRAWAL STATE!"); + + return StateResult.FINISHED; + } + + @Override + public byte move(AIActor actor) { + DevLog.debugoutai(actor, "Charon", "AI WithdrawalState", "WITHDRAWAL MOVE!"); + if (locked){ + System.out.println("WITHDRAWAL locked!"); + return StateResult.FINISHED; + } + if (actor==null) + return StateResult.FINISHED; + CreatureObject creature = actor.getCreature(); + if (creature==null) + return StateResult.FINISHED; + +// if(creature.isInCombat()){ +// //System.out.println("PatrolState locking!"); +// locked = true; +// return StateResult.FINISHED; +// } + doWithdrawal(actor); + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + + @Override + public byte recover(AIActor actor) { + if (actor.getFollowObject()!=null) + System.out.println("recover follow object is not null"); + if (actor.getFollowObject()!=null) + System.out.println("recover follow object is not null"); + return StateResult.UNFINISHED; + } +} diff --git a/src/services/combat/CombatEvents.java b/src/services/combat/CombatEvents.java index 3dc20ee0..e0e1bbf9 100644 --- a/src/services/combat/CombatEvents.java +++ b/src/services/combat/CombatEvents.java @@ -21,14 +21,14 @@ ******************************************************************************/ package services.combat; -import resources.objects.creature.CreatureObject; import engine.resources.common.Event; +import engine.resources.objects.SWGObject; public class CombatEvents implements Event { public class DamageTaken implements Event { - public CreatureObject attacker; + public SWGObject attacker; public int damage; } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 21eec82c..beb6d6c0 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -54,12 +54,14 @@ import resources.datatables.Elemental; import resources.datatables.Posture; import resources.datatables.WeaponType; import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; import resources.objects.mission.MissionObject; import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import resources.objects.waypoint.WaypointObject; import resources.objects.weapon.WeaponObject; import services.ai.AIActor; +import services.ai.TurretAIActor; import services.combat.CombatEvents.DamageTaken; import services.command.CombatCommand; import services.sui.SUIService.MessageBoxType; @@ -240,6 +242,148 @@ public class CombatService implements INetworkDispatch { } } } + + public void doCombatForInstallation(final InstallationObject attacker, final TangibleObject target, final WeaponObject weapon, final CombatCommand command, final int actionCounter) { + if(target instanceof CreatureObject) if(((CreatureObject) target).getPosture() == Posture.Incapacitated || ((CreatureObject) target).getPosture() == Posture.Dead) return; + + boolean success = true; + +// if((command.getAttackType() == 0 || command.getAttackType() == 1 || command.getAttackType() == 3) && !attemptCombat(attacker, target)) +// success = false; + +// if(success && !applySpecialCost(attacker, weapon, command)) +// success = false; + + if(!success) { + IoSession session = attacker.getClient().getSession(); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); + session.write(new ObjControllerMessage(0x0B, commandRemove).serialize()); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), -1); + session.write(new ObjControllerMessage(0x0B, startTask).serialize()); + return; + } + + //final Point3D targetPos = target.getPosition(); + //final SWGObject targetParent = target.getContainer(); + + if(command.getDelayAttackParticle().length() > 0 || command.getInitialAttackDelay() > -1) { + + if(command.getInitialAttackDelay() > 0) { + + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + try { + Thread.sleep((long) command.getInitialAttackDelay() * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + } else if(command.getInitialAttackDelay() <= 0 && command.getDelayAttackInterval() > 0 && command.getDelayAttackLoops() <= 1) { + + try { + Thread.sleep((long) command.getDelayAttackInterval() * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + } + + if(command.getDelayAttackLoops() > 1) { + final ScheduledFuture task = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 0, (long) (command.getDelayAttackInterval() * 1000), TimeUnit.MILLISECONDS); + + scheduler.schedule(new Runnable() { + + @Override + public void run() { + try { + task.cancel(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, (long) ((command.getDelayAttackInterval() * 1000) * command.getDelayAttackLoops()), TimeUnit.MILLISECONDS); + + return; + + } else { + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent); + } + + } else { + + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, target, weapon, command, actionCounter); + + } + + if(target instanceof CreatureObject) + { + CreatureObject creature = (CreatureObject)target; + if(creature.getPosture() == Posture.Incapacitated || creature.getPosture() == Posture.Dead) + { + for (TangibleObject defender : new ArrayList(creature.getDefendersList())) + { + defender.removeDefender(creature); + creature.removeDefender(defender); + } + + if(((CreatureObject) target).getPlayerObject() == null) + { + target.setKiller(attacker); + + scheduler.schedule(new Runnable() + { + @Override + public void run() + { + try { + core.objectService.destroyObject(target); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 2, TimeUnit.MINUTES); + } + } + } + else if(target instanceof TangibleObject) + { + if(target.getConditionDamage() == target.getMaximumCondition()) + { + for(TangibleObject defender : target.getDefendersList()) defender.removeDefender(target); + core.objectService.destroyObject(target); + } + } + } private void doAreaCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { if(target instanceof CreatureObject) { @@ -313,6 +457,24 @@ public class CombatService implements INetworkDispatch { } + private void doSingleTargetCombatForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + if(target instanceof CreatureObject) { + doSingleTargetCombatForInstallation(attacker, (CreatureObject) target, weapon, command, actionCounter); + return; + } + + float damage = calculateDamageForInstallation(attacker, target, weapon, command); + + if(damage > 0) + applyDamageForInstallation(attacker, target, (int) damage); + + sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT); + + if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage); + + } + private void applyDamage(CreatureObject attacker, TangibleObject target, int damage) { target.setConditionDamage(target.getConditionDamage() + damage); @@ -321,6 +483,39 @@ public class CombatService implements INetworkDispatch { core.mountService.damage((CreatureObject) target); } + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject)target; + if (targetCreature.getCalledPet()!=null) { + AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI"); + if (petActor!=null){ + petActor.addDefender(attacker); + DevLog.debugoutai(petActor, "Charon", "Pet AI", "applyDamage addDefender"); + } + } + + if (!targetCreature.isInCombat()){ + //targetCreature.setInCombat(true); + AIActor targetActor = (AIActor) targetCreature.getAttachment("AI"); + targetActor.addDefender(attacker); + DevLog.debugoutai(targetActor, "Charon", "CombatService AI", "applyDamage addDefender 2"); + } + } + + DamageTaken event = events.new DamageTaken(); + event.attacker = attacker; + event.damage = damage; + target.getEventBus().publish(event); + attacker.setTefTime(300000); + } + + private void applyDamageForInstallation(InstallationObject attacker, TangibleObject target, int damage) { + + target.setConditionDamage(target.getConditionDamage() + damage); + + if (target.getOption(Options.MOUNT)) { + core.mountService.damage((CreatureObject) target); + } + if (target instanceof CreatureObject){ CreatureObject targetCreature = (CreatureObject)target; if (targetCreature.getCalledPet()!=null) { @@ -330,15 +525,133 @@ public class CombatService implements INetworkDispatch { DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); } } + + if (!targetCreature.isInCombat()){ + //targetCreature.setInCombat(true); + AIActor targetActor = (AIActor) targetCreature.getAttachment("AI"); + targetActor.addDefender(attacker); + DevLog.debugout("Charon", "CombatService AI", "applyDamage addDefender 2"); + } } DamageTaken event = events.new DamageTaken(); event.attacker = attacker; event.damage = damage; target.getEventBus().publish(event); - System.out.println("APPLY DAMAGE2"); - attacker.setTefTime(300000); + //attacker.setTefTime(300000); } + + private void applyDamageForInstallation(InstallationObject attacker, CreatureObject target, int damage) { + + if(target.getHealth() - damage <= 0 && target.getSlottedObject("ghost") != null) { + + if(target.hasBuff("incapWeaken")) { + + //AIActor aiActor = (AIActor)attacker.getAttachment("AI"); + + deathblowPlayerFromInstallation(attacker, target); + return; + } + + + + if (attacker.getAttachment("AI") instanceof AIActor){ + AIActor aiActor = (AIActor)attacker.getAttachment("AI"); + if (aiActor.getMobileTemplate().isDeathblow()){ + deathblowPlayerFromInstallation(attacker, target); + return; + } + } + if (attacker.getAttachment("AI") instanceof TurretAIActor){ + deathblowPlayerFromInstallation(attacker, target); // turrets always db + return; + + } + + synchronized(target.getMutex()) { + if (core.mountService.isMounted(target)) { + core.mountService.dismount(target, (CreatureObject) target.getContainer()); + } + + target.setHealth(1); + target.setPosture(Posture.Incapacitated); + target.setTurnRadius(0); + target.setSpeedMultiplierBase(0); + + } + + ScheduledFuture incapTask = scheduler.schedule(() -> { + + synchronized(target.getMutex()) { + try { + if(target.getPosture() != 13) + return; + + target.setPosture(Posture.Upright); + target.setTurnRadius(1); + target.setSpeedMultiplierBase(1); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, target.getIncapTimer(), TimeUnit.SECONDS); + target.setIncapTask(incapTask); + core.buffService.addBuffToCreature(target, "incapWeaken", target); + if(target.getSlottedObject("ghost") != null && attacker.getSlottedObject("ghost") != null) { + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", attacker.getCustomName()), DisplayType.Broadcast); + //attacker.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_target_incap", "TT", target.getCustomName()), DisplayType.Broadcast); + } else {target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast); } + return; + } else if(target.getHealth() - damage <= 0 && target.getAttachment("AI") != null) { + synchronized(target.getMutex()) { + target.setHealth(0); + target.setPosture(Posture.Dead); + } + attacker.removeDefender(target); + target.removeDefender(attacker); + return; + } + synchronized(target.getMutex()) { + target.setHealth(target.getHealth() - damage); + } + + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject)target; + if (targetCreature.getCalledPet()!=null) { + AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI"); + if (petActor!=null){ + petActor.addDefender(attacker); + DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); + } + } + + if (!targetCreature.isInCombat()){ + //targetCreature.setInCombat(true); + if (targetCreature.getAttachment("AI") instanceof AIActor){ + AIActor targetActor = (AIActor) targetCreature.getAttachment("AI"); + targetActor.addDefender(attacker); + DevLog.debugoutai(targetActor, "Charon", "CombatService AI", "applyDamage addDefender 2"); + } + if (targetCreature.getAttachment("AI") instanceof TurretAIActor){ + TurretAIActor targetActor = (TurretAIActor) targetCreature.getAttachment("AI"); + targetActor.addDefender(attacker); + DevLog.debugoutai(targetActor, "Charon", "CombatService AI", "applyDamage addDefender 2"); + } + } + } + + + if (target.getPosture()!=13){ + DamageTaken event = events.new DamageTaken(); + event.attacker = attacker; + event.damage = damage; + target.getEventBus().publish(event); + } + } + + private void doAreaCombat(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { @@ -455,11 +768,39 @@ public class CombatService implements INetworkDispatch { sendCombatPackets(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT); } + + private void doSingleTargetCombatForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + float damage = calculateDamageForInstallation(attacker, target, weapon, command); + if(damage > 0) { + damage *= 1.5f; + int damageBeforeArmor = (int) damage; + damage *= 0.99; + int armorAbsorbed = (int) (damageBeforeArmor - damage); + + if(damage > 0) + applyDamageForInstallation(attacker, target, (int) damage); + + sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, armorAbsorbed, HitType.CRITICAL); + + if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage); + + return; + } + } private void sendCombatPackets(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { - String animationStr = command.getRandomAnimation(weapon); + String animationStr = command.getRandomAnimation(weapon); // choosing turretShot as default attack, results in a zero length string + if (weapon.getTemplate().contains("atst_ranged")) + animationStr="fire_1_single_light"; + CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + +// int turret_fire = 0xD334C0B8; // 0xA7595B4E +// CombatAction combatAction = new CombatAction(turret_fire, attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); +// ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); attacker.notifyObserversInRange(objController, true, 125); CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType); @@ -485,6 +826,21 @@ public class CombatService implements INetworkDispatch { } + private void sendCombatPacketsForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { + + //String animationStr = command.getRandomAnimation(weapon); + int turret_fire = 0xD334C0B8; // 0xA7595B4E + //CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + CombatAction combatAction = new CombatAction(turret_fire, attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); + attacker.notifyObserversInRange(objController, true, 125); + CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType); + ObjControllerMessage objController4 = new ObjControllerMessage(0x1B, combatSpam); + IoBuffer spam = objController4.serialize(); + if(target.getClient() != null) + target.getClient().getSession().write(spam); + } + private void sendHealPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { CombatAction combatAction = new CombatAction(CRC.StringtoCRC(command.getDefaultAnimations()[0]), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); @@ -682,6 +1038,23 @@ public class CombatService implements INetworkDispatch { return rawDamage; } + + private float calculateDamageForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + if(command.getPercentFromWeapon() > 0) { + + float weaponMinDmg = weapon.getMinDamage(); + float weaponMaxDmg = weapon.getMaxDamage(); + + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + } + return rawDamage; + } private float calculateDamage(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) { @@ -717,6 +1090,28 @@ public class CombatService implements INetworkDispatch { } + if (!attacker.isPlayer()){ + if (attacker.hasBuff("expertise_damage_npc")){ + rawDamage *=2; // tower_defense buff + } + } + } + + return rawDamage; + } + + private float calculateDamageForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + + if(command.getPercentFromWeapon() > 0 && weapon != attacker.getSlottedObject("default_weapon")) { + + float weaponMinDmg = weapon.getMinDamage(); + float weaponMaxDmg = weapon.getMaxDamage(); + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; } return rawDamage; @@ -916,9 +1311,15 @@ public class CombatService implements INetworkDispatch { AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI"); if (petActor!=null){ petActor.addDefender(attacker); - DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); + //DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); } } + + if (!targetCreature.isInCombat()){ + AIActor targetActor = (AIActor) targetCreature.getAttachment("AI"); + targetActor.addDefender(attacker); + //DevLog.debugout("Charon", "CombatService AI", "applyDamage addDefender 2"); + } } @@ -1148,6 +1549,26 @@ public class CombatService implements INetworkDispatch { core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null); } + + public void deathblowPlayerFromInstallation(InstallationObject attacker, CreatureObject target) { + target.stopIncapTask(); + target.setIncapTask(null); + target.setPosture(Posture.Dead); + + + attacker.removeDefender(target); + target.removeDefender(attacker); + target.setSpeedMultiplierBase(0); + target.setTurnRadius(0); + + if (attacker.getSlottedObject("ghost") != null) + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", attacker.getCustomName()), DisplayType.Broadcast); + else + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast); + + core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null); + } + public boolean areInDuel(CreatureObject creature1, CreatureObject creature2) { if(creature1.getDuelList().contains(creature2) && creature2.getDuelList().contains(creature1)) @@ -1385,7 +1806,7 @@ public class CombatService implements INetworkDispatch { if(creature.getClient() == null) { if (creature.getAttachment("AI")!=null){ AIActor aiActor = (AIActor) creature.getAttachment("AI"); - CreatureObject target = aiActor.getFollowObject(); + TangibleObject target = aiActor.getFollowObject(); if (target.getClient()!=null) client = target.getClient(); // Use player's client reference that is in combat with that NPC } diff --git a/src/services/command/BaseSWGCommand.java b/src/services/command/BaseSWGCommand.java index 5025939d..87dff513 100644 --- a/src/services/command/BaseSWGCommand.java +++ b/src/services/command/BaseSWGCommand.java @@ -76,7 +76,10 @@ public class BaseSWGCommand implements Cloneable { if (((String) visitor2.getObject(i, 0)).equalsIgnoreCase(commandName)) { int sub = 0; // Subtract due to command table structures being different - characterAbility = (String) visitor2.getObject(i, 7); + if(((String) visitor2.getObject(i, 7)).equals("admin")) + characterAbility = ""; + else + characterAbility = (String) visitor2.getObject(i, 7); for (int l = (8 - sub); l <= (29 - sub); l++) { if (!((Boolean) visitor2.getObject(i, l))) { diff --git a/src/services/command/CommandService.java b/src/services/command/CommandService.java index ab02d15f..2f9962cd 100644 --- a/src/services/command/CommandService.java +++ b/src/services/command/CommandService.java @@ -21,9 +21,14 @@ ******************************************************************************/ package services.command; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteOrder; import java.util.Map; +import java.util.Scanner; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -31,6 +36,7 @@ import java.util.concurrent.ScheduledExecutorService; import main.NGECore; +import org.apache.commons.io.FileUtils; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; @@ -50,6 +56,7 @@ import protocol.swg.objectControllerObjects.CommandEnqueueRemove; import protocol.swg.objectControllerObjects.StartTask; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; @@ -70,29 +77,23 @@ public class CommandService implements INetworkDispatch { public boolean callCommand(CreatureObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { - if (actor == null) { + if (actor == null) return false; - } - if (command == null) { + if (actor.getClient() == null) return false; - } - if (command.getCharacterAbility().length() > 0 && !actor.hasAbility(command.getCharacterAbility()) && actor.getClient() != null) { + if (command == null) return false; - } - if (command.isDisabled()) { + if (command.getCharacterAbility().length() > 0 && !actor.hasAbility(command.getCharacterAbility())) return false; - } - if (actor.getClient() != null && command.getGodLevel() > actor.getPlayerObject().getGodLevel()) { + if (command.isDisabled()) return false; - } - if (actor.hasCooldown(command.getCooldownGroup()) || actor.hasCooldown(command.getCommandName())) { + if (actor.hasCooldown(command.getCooldownGroup()) || actor.hasCooldown(command.getCommandName())) return false; - } // Causes this service method to return with false after equipping a rifle, not allowing to unequip it anymore // because the client seems to consider rifles invalidweapons for an unkown reason @@ -152,6 +153,7 @@ public class CommandService implements INetworkDispatch { if (!core.simulationService.checkLineOfSight(actor, target)) { actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + // If this is AI consider side steps to get LOS return false; } @@ -331,8 +333,255 @@ public class CommandService implements INetworkDispatch { return true; } + public boolean callCommandForInstallation(InstallationObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { + + if (actor == null) { + return false; + } + + if (command == null) { + return false; + } + + if (command.isDisabled()) { + return false; + } + +// if (actor.hasCooldown(command.getCooldownGroup()) || actor.hasCooldown(command.getCommandName())) { +// return false; +// } + + //TangibleObject weapon = (TangibleObject) core.objectService.getObject(actor.getWeaponId()); + TangibleObject weapon = (TangibleObject) core.objectService.getObject((long)actor.getAttachment("TurretWeapon")); + + if (weapon != null && weapon instanceof WeaponObject && ((WeaponObject) weapon).getWeaponType() == command.getInvalidWeapon()) { + System.out.println("Invalid WEAPON!"); + return false; + } + + + + switch (command.getTargetType()) { + case 0: // Target Not Used For This Command + break; + case 1: // Other Only (objectId/targetName) + if (target == null || target == actor) { + if (commandArgs != null && !commandArgs.equals("")) { + String name = commandArgs.split(" ")[0]; + + target = core.objectService.getObjectByFirstName(name); + + if (target == actor) { + target = null; + } + } + + break; + } + + if (target == actor) { + return false; + } + + if (target.getContainer() == actor || target.getGrandparent() == actor) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + // If this is AI consider side steps to get LOS + return false; + } + + break; + case 2: // Anyone (objectId/targetName) + if (target == null) { + if (commandArgs != null && !commandArgs.equals("")) { + String name = commandArgs.split(" ")[0]; + + target = core.objectService.getObjectByFirstName(name); + + if (target == actor) { + target = null; + } + + // It's possible they use c cmdString to indicate if it should always be on self + if (name.contains("c")) { + //target = actor; + } + } + + break; + } + + if (target.getContainer() == actor || target.getGrandparent() == actor) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + return false; + } + + break; + case 3: // Free Target Mode (rally points, group waypoints) + target = null; + + if (commandArgs == null) { + break; + } + + String[] args = commandArgs.split(" "); + + float x = 0, y = 0, z = 0; + + try { + if (args.length == 2) { + x = Integer.valueOf(args[0]); + z = Integer.valueOf(args[1]); + } else if (args.length > 2) { + x = Integer.valueOf(args[0]); + y = Integer.valueOf(args[1]); + z = Integer.valueOf(args[2]); + } else { + return false; + } + } catch (NumberFormatException e) { + return false; + } + + Point3D position = new Point3D(x, y, z); + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(position) > command.getMaxRangeToTarget()) { + return false; + } + + break; + case 4: // Any object + if (target == null) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + return false; + } + + break; + default: + break; + } + switch (command.getTarget()) { + case 0: // Ally Only + if (target == null) { + target = actor; + } + + if (!(target instanceof TangibleObject)) { + return false; + } + + TangibleObject object = (TangibleObject) target; + + if (!object.getFaction().equals("") && !object.getFaction().equals(actor.getFaction())) { + return false; + } + + if (actor.getFactionStatus() < object.getFactionStatus()) { + return false; + } + +// if (object.isAttackableBy(actor)) { +// return false; +// } + + // Without this we could be buffing ally NPCs and such + // Think this is checked later on + if (actor.getSlottedObject("ghost") != null && object.getSlottedObject("ghost") == null) { + return false; + } + + break; + case 1: // Enemy Only + if (target == null || !(target instanceof TangibleObject)) { + return false; + } + + TangibleObject targetObject = (TangibleObject) target; + +// if (!targetObject.isAttackableBy(actor)) { +// return false; +// } + + break; + case 2: // Indifferent + break; + default: + break; + } + +// if (command.shouldCallOnTarget()) { +// if (target == null || !(target instanceof CreatureObject)) { +// return false; +// } +// +// actor = (CreatureObject) target; +// } + + long warmupTime = (long) (command.getWarmupTime() * 1000f); + + if(warmupTime > 0) { + try { + Thread.sleep(warmupTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if(command instanceof CombatCommand) { + try { + processCommandForInstallation(actor, target, (BaseSWGCommand) command.clone(), actionCounter, commandArgs); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } + else + processCommandForInstallation(actor, target, command, actionCounter, commandArgs); + + + return true; + } + public void callCommand(SWGObject actor, String commandName, SWGObject target, String commandArgs) { - callCommand((CreatureObject) actor, target, getCommandByName(commandName), 0, commandArgs); + if (actor instanceof CreatureObject) + callCommand((CreatureObject) actor, target, getCommandByName(commandName), 0, commandArgs); + if (actor instanceof InstallationObject) + callCommandForInstallation((InstallationObject) actor, target, getCommandByName(commandName), 0, commandArgs); } public BaseSWGCommand getCommandByCRC(int commandCRC) { @@ -438,12 +687,59 @@ public class CommandService implements INetworkDispatch { } public void processCommand(CreatureObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { + + if (command.getGodLevel() > 0 || command.getCommandName().equals("setgodmode")) { // TODO: When loading commands, simply don't put the "admin" characterAbility into the commands + String accessLevel = core.adminService.getAccessLevelFromDB(actor.getClient().getAccountId()); + + if(accessLevel != null) { + Scanner scanner; + try { + scanner = new Scanner(new File("accesslevels/" + accessLevel + ".txt")); + boolean levelHasCommand = false; + + while(scanner.hasNextLine()) { + String commandName = scanner.nextLine(); + if(command.getCommandName().equals(commandName)) { + levelHasCommand = true; + break; + } + } + + if (!levelHasCommand) { + actor.sendSystemMessage(" \\#FE2EF7 [GM] \\#FFFFFF " + command.getCommandName() + ": You do not have permission to use this command.", (byte) 0); + return; + } + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + if (command.getCooldown() > 0f) { actor.addCooldown(command.getCooldownGroup(), command.getCooldown()); } if (command instanceof CombatCommand) { processCombatCommand(actor, target, (CombatCommand) command, actionCounter, commandArgs); + } else + if (FileUtilities.doesFileExist("scripts/commands/" + command.getCommandName().toLowerCase() + ".py")) { + core.scriptService.callScript("scripts/commands/", command.getCommandName().toLowerCase(), "run", core, actor, target, commandArgs); + } else if (FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName().toLowerCase() + ".py")) { + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName().toLowerCase(), "run", core, actor, target, commandArgs); + } + + + } + + public void processCommandForInstallation(InstallationObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { +// if (command.getCooldown() > 0f) { +// actor.addCooldown(command.getCooldownGroup(), command.getCooldown()); +// } + + if (command instanceof CombatCommand) { + processCombatCommandForInstallation(actor, target, (CombatCommand) command, actionCounter, commandArgs); } else { if (FileUtilities.doesFileExist("scripts/commands/" + command.getCommandName().toLowerCase() + ".py")) { core.scriptService.callScript("scripts/commands/", command.getCommandName().toLowerCase(), "run", core, actor, target, commandArgs); @@ -557,6 +853,100 @@ public class CommandService implements INetworkDispatch { } + public void processCombatCommandForInstallation(InstallationObject attacker, SWGObject target, CombatCommand command, int actionCounter, String commandArgs) { + if (FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) { + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "setup", core, attacker, target, command); + } + + boolean success = true; + + //if((command.getHitType() == 5 || command.getHitType() == 7) && !(target instanceof CreatureObject)) + // success = false; + + if(!(command.getAttackType() == 2) && !(command.getHitType() == 5) && !(command.getHitType() == 0)) { + if(target == null || !(target instanceof TangibleObject) || target == attacker) + success = false; + } else { + if(target == null) + target = attacker; + else if(!(target instanceof TangibleObject)) + return; + } + + if(target instanceof CreatureObject) { + if(!(command.getHitType() == 5)) + if(((CreatureObject) target).getPosture() == 13) + success = false; + if(!(command.getHitType() == 7)) + if(((CreatureObject) target).getPosture() == 14) + success = false; + } + + if(command.getHitType() == 7 && target.getClient() == null) + success = false; + + WeaponObject weapon; + + + weapon = (WeaponObject) core.objectService.getObject((long)attacker.getAttachment("TurretWeapon")); + + if(weapon == null) + return; + + float maxRange = 0; + + if(command.getMaxRange() == 0) + maxRange = weapon.getMaxRange(); + else + maxRange = command.getMaxRange(); + + Point3D attackerPos = attacker.getWorldPosition(); + Point3D defenderPos = attacker.getWorldPosition(); + + if(attackerPos.getDistance(defenderPos) > maxRange && maxRange != 0) + success = false; + + if(command.getMinRange() > 0) { + if(attackerPos.getDistance(defenderPos) < command.getMinRange()) + success = false; + } + + + if(target != attacker && success && !core.simulationService.checkLineOfSight(attacker, target)) { + attacker.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + success = false; + } + + if(!success && attacker.getClient() != null) { + IoSession session = attacker.getClient().getSession(); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); + session.write(new ObjControllerMessage(0x0B, commandRemove).serialize()); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), -1); + session.write(new ObjControllerMessage(0x0B, startTask).serialize()); + } else { + +// if(command.getHitType() == 5) { +// core.combatService.doHeal(attacker, (CreatureObject) target, weapon, command, actionCounter); +// return; +// } +// +// if(command.getHitType() == 7) { +// core.combatService.doRevive(attacker, (CreatureObject) target, weapon, command, actionCounter); +// return; +// } +// +// if(command.getHitType() == 0 && command.getBuffNameSelf() != null && command.getBuffNameSelf().length() > 0) { +// core.combatService.doSelfBuff(attacker, weapon, command, actionCounter); +// return; +// } + for(int i = 0 ; i < command.getAttack_rolls(); i++) { + core.combatService.doCombatForInstallation(attacker, (TangibleObject) target, weapon, command, actionCounter); + } + + } + + } + public void removeCommand(CreatureObject actor, int actionCounter, BaseSWGCommand command) { if (actor == null || actor.getClient() == null || command == null) { return; diff --git a/src/services/gcw/FactionService.java b/src/services/gcw/FactionService.java index df74bf0c..2ba2a347 100644 --- a/src/services/gcw/FactionService.java +++ b/src/services/gcw/FactionService.java @@ -21,6 +21,7 @@ ******************************************************************************/ package services.gcw; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; @@ -37,6 +38,7 @@ import org.python.core.Py; import org.python.core.PyObject; import protocol.swg.FactionResponseMessage; +import protocol.swg.UpdatePVPStatusMessage; import resources.common.FileUtilities; import resources.common.Opcodes; import resources.datatables.DisplayType; @@ -44,6 +46,7 @@ import resources.datatables.FactionStatus; import resources.datatables.Options; import resources.datatables.PvpStatus; import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; import resources.objects.mission.MissionObject; import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; @@ -52,6 +55,7 @@ import engine.clientdata.StfTable; import engine.clientdata.visitors.DatatableVisitor; import engine.clients.Client; import engine.resources.common.CRC; +import engine.resources.objects.SWGObject; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; @@ -169,6 +173,7 @@ public class FactionService implements INetworkDispatch { * Will be useful for NPC AI, so they know who to help and who to be indifferent to. */ public boolean isFactionAlly(TangibleObject object, TangibleObject target) { + if (object == null || target == null) { return false; } @@ -180,10 +185,10 @@ public class FactionService implements INetworkDispatch { return false; } + if (FileUtilities.doesFileExist("scripts/faction/" + objectFaction + ".py")) { - PyObject method = core.scriptService.getMethod("scripts/faction/", objectFaction, "isAlly"); - - if (method != null && method.isCallable()) { + PyObject method = core.scriptService.getMethod("scripts/faction/", objectFaction, "isAlly"); + if (method != null && method.isCallable()) { return ((method.__call__(Py.java2py(targetFaction)).asInt() == 1) ? true : false); } } @@ -191,6 +196,29 @@ public class FactionService implements INetworkDispatch { return false; } + public boolean isFactionAlly(String objectFaction, String targetFaction) { + + if (objectFaction == null || targetFaction == null) { + return false; + } + + if (!isFaction(objectFaction) || !isFaction(targetFaction)) { + return false; + } + + + if (FileUtilities.doesFileExist("scripts/faction/" + objectFaction + ".py")) { + PyObject method = core.scriptService.getMethod("scripts/faction/", objectFaction, "isAlly"); + if (method != null && method.isCallable()) { + return ((method.__call__(Py.java2py(targetFaction)).asInt() == 1) ? true : false); + } + } + + return false; + } + + + /* * Returns true if target is an enemy of object * @@ -212,13 +240,22 @@ public class FactionService implements INetworkDispatch { PyObject method = core.scriptService.getMethod("scripts/faction/", objectFaction, "isEnemy"); if (method != null && method.isCallable()) { - return ((method.__call__(Py.java2py(targetFaction)).asInt() == 1) ? true : false); + int checkResult = method.__call__(Py.java2py(targetFaction)).asInt(); + if (objectFaction.equals("rebel") || objectFaction.equals("imperial")){ + if (object.getFactionStatus()==FactionStatus.OnLeave) + checkResult=0; + } + if (targetFaction.equals("rebel") || targetFaction.equals("imperial")){ + if (target.getFactionStatus()==FactionStatus.OnLeave) + checkResult=0; + } + return ((checkResult == 1) ? true : false); } } return false; } - + /* * Calculates the target's pvp bitmask based on the person's * faction standing and the enemy's options bitmask. @@ -239,6 +276,10 @@ public class FactionService implements INetworkDispatch { PlayerObject ghost = (PlayerObject) object.getSlottedObject("ghost"); int pvpBitmask = 0; + + if (target==null) + return 0; // Avoids infinite loading screen when another player character has been deleted, + // but is still referenced by some collections being null if (object == target) { pvpBitmask |= PvpStatus.Self; @@ -263,7 +304,7 @@ public class FactionService implements INetworkDispatch { if (target.getFactionStatus() == FactionStatus.SpecialForces) { pvpBitmask |= PvpStatus.Overt; } - + // Everything below assumes target is potentially attackable. if (!target.getOption(Options.ATTACKABLE) || target.getOption(Options.INVULNERABLE)) { return pvpBitmask; @@ -355,6 +396,7 @@ public class FactionService implements INetworkDispatch { } } + return pvpBitmask; } @@ -525,6 +567,54 @@ public class FactionService implements INetworkDispatch { return factionMap; } + // This is to make nearby NPCs transmit updatepvp, + // so the player sees the faction change represented in the clientside NPC representation + public void updatePVPFromNearbyNPCs(CreatureObject creature, Client destination){ + List awareObjects = core.simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 512); + for(int i = 0; i < awareObjects.size(); i++) { + SWGObject obj = awareObjects.get(i); + if(obj != creature && obj.getContainer() != creature && obj.isInQuadtree()) { + if (obj instanceof CreatureObject){ + CreatureObject creo = (CreatureObject) obj; + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(creo.getObjectID()); + upvpm.setFaction(CRC.StringtoCRC(creo.getFaction())); + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), creo)); + destination.getSession().write(upvpm.serialize()); + } + if (obj instanceof TangibleObject && !(obj instanceof CreatureObject)){ + TangibleObject tano = (TangibleObject) obj; + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(tano.getObjectID()); + upvpm.setFaction(CRC.StringtoCRC(tano.getFaction())); + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((TangibleObject) destination.getParent(), tano)); + destination.getSession().write(upvpm.serialize()); + + // Crashes client and more importantly should be done selectively with different destinations +// if (destination.getParent() instanceof CreatureObject){ +// //System.out.println("IN updatePVPFromNearbyNPCs!!!!!!!" + destination.getParent().getCustomName()); +// if (((CreatureObject) destination.getParent()).isPlayer() && ((CreatureObject) destination.getParent()).getFaction()!=tano.getFaction()){ +// int optionsBitMask = tano.getOptionsBitmask(); +// if (tano.getOption(Options.QUEST)) +// optionsBitMask = optionsBitMask & ~Options.QUEST; +// if (!tano.getOption(Options.ATTACKABLE)) +// optionsBitMask = optionsBitMask | Options.ATTACKABLE; +// +// tano.setOptionsBitmask(optionsBitMask); +// } +// } + + } + if (obj instanceof InstallationObject && !(obj instanceof TangibleObject)){ + InstallationObject inso = (InstallationObject) obj; + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(inso.getObjectID()); + upvpm.setFaction(CRC.StringtoCRC(inso.getFaction())); + upvpm.setStatus(NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), inso)); + //System.out.println("MakeAwareNearbyNPCs " + NGECore.getInstance().factionService.calculatePvpStatus((CreatureObject) destination.getParent(), inso)); + destination.getSession().write(upvpm.serialize()); + } + } + } + } + @Override public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { diff --git a/src/services/gcw/GCWPylon.java b/src/services/gcw/GCWPylon.java new file mode 100644 index 00000000..60ef29f0 --- /dev/null +++ b/src/services/gcw/GCWPylon.java @@ -0,0 +1,398 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.gcw; + +import java.util.Map; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import main.NGECore; +import protocol.swg.PlayClientEffectObjectTransformMessage; +import engine.clients.Client; +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.datatables.FactionStatus; +import resources.datatables.Factions; +import resources.datatables.Options; +import resources.datatables.WeaponType; +import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.TurretAIActor; + +/** + * @author Charon + */ + +public class GCWPylon extends TangibleObject{ + + private static final long serialVersionUID = 1L; + private int pylonType = 0; + private int pylonFaction = 0; + private int spawnLevel = 0; + private int patrolRoute = 0; + private int resourceFilling = 0; + private int delay = 0; + + private static Map typeStfMapping = new ConcurrentHashMap(); + static{ + typeStfMapping.put(PylonType.SoldierPatrol, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.SoldierDefense, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.VehiclePatrol, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.SiegeVehiclePatrol, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.Barricade, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.Turret, "Soldier Patrol Pylon"); + typeStfMapping.put(PylonType.Tower, "Soldier Patrol Pylon"); + } + + + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public GCWPylon() { + super(); + } + + public GCWPylon(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ + super(objectID, planet, position, orientation, template); + this.setAttachment("Filling",0); + this.setResourceFilling(0); + } + + public int getPylonType() { + return pylonType; + } + + public void setPylonType(int pylonType) { + this.pylonType = pylonType; + + String pylonName = ""; + switch (pylonType){ + case PylonType.Barricade: pylonName="Barricade Construction Site"; + break; + case PylonType.SoldierDefense: pylonName="Soldier Construction Site"; + break; + case PylonType.SoldierPatrol: pylonName="Patrol Construction Site"; + break; + case PylonType.VehiclePatrol: pylonName="Vehicle Construction Site"; + break; + case PylonType.SiegeVehiclePatrol: pylonName="Siege Vehicle Construction Site"; + break; + case PylonType.Tower: pylonName="Tower Construction Site"; + break; + case PylonType.Turret: pylonName="Turret Construction Site"; + break; + } + + this.setCustomName(pylonName + " 0/100"); + this.setAttachment("Name", pylonName); + + } + + public int getPylonFaction() { + return pylonFaction; + } + + public void setPylonFaction(int pylonFaction) { + this.pylonFaction = pylonFaction; + } + + public int getSpawnLevel() { + return spawnLevel; + } + + public void setSpawnLevel(int spawnLevel) { + this.spawnLevel = spawnLevel; + } + + public void setPatrolRoute(int route){ + this.patrolRoute = route; + } + + public int getPatrolRoute(){ + return this.patrolRoute; + } + + public void convertToPhase2Object(){ + + //if (determinePylonLevel()==0) + //return; + + resourceFilling = 100; + spawnLevel = 3; +// resourceFilling = 10; +// spawnLevel = 1; + + switch (pylonType){ + case PylonType.Barricade: createBarricade(); + break; + case PylonType.SoldierDefense: createSpawner(); + break; + case PylonType.SoldierPatrol: createSpawner(); + break; + case PylonType.VehiclePatrol: createSpawner(); + break; + case PylonType.SiegeVehiclePatrol: createSpawner(); + break; + case PylonType.Tower: createTower(); + break; + case PylonType.Turret: createTurret(); + break; + } + } + + public int determinePylonLevel(){ + if (resourceFilling==0) spawnLevel = 0; + if (resourceFilling>0 && resourceFilling<50) spawnLevel = 1; + if (resourceFilling>=50 && resourceFilling<100) spawnLevel = 2; + if (resourceFilling==100) spawnLevel = 3; + return spawnLevel; + } + + + public void createSpawner(){ + GCWSpawner spawner = (GCWSpawner) NGECore.getInstance().objectService.createObject("object/tangible/loot/creature_loot/collections/shared_dejarik_table_base.iff", 0, this.getPlanet(), this.getWorldPosition(), this.getOrientation()); + NGECore.getInstance().simulationService.add(spawner, spawner.getPosition().x, spawner.getPosition().z, true); + spawner.setCustomName(""); + spawner.setStfFilename("battlefield"); + spawner.setStfName("battlefield_marker_name"); + spawner.setPatrolRoute(getPatrolRoute()); + spawner.setDelay(getDelay()); + spawner.setSpawnLevel(3); + spawner.setSpawnerFaction(getPylonFaction()); + spawner.setSpawnerType(getPylonType()); + NGECore.getInstance().invasionService.registerPhase2Objects(spawner); + } + + public void createTurret(){ + String turretTemplate="object/installation/turret/gcw/shared_adv_turret_dish_sm_heat.iff"; + //String turretTemplate="object/installation/turret/gcw/shared_adv_turret_dish_large_heat.iff"; + if (spawnLevel==2) turretTemplate="object/installation/turret/gcw/shared_adv_turret_dish_large_heat.iff"; + if (spawnLevel==3) turretTemplate="object/installation/turret/gcw/shared_adv_turret_block_med_heat.iff"; + Planet spawnPlanet = this.getPlanet(); + Point3D spawnPos = this.getWorldPosition(); + Quaternion quat = this.getOrientation(); + NGECore.getInstance().objectService.destroyObject(this.getObjectID()); + InstallationObject turret = (InstallationObject) NGECore.getInstance().objectService.createObject(turretTemplate, 0, spawnPlanet, spawnPos, quat); + NGECore.getInstance().simulationService.add(turret, turret.getPosition().x, turret.getPosition().z, true); + float positionY = NGECore.getInstance().terrainService.getHeight(turret.getPlanetId(), turret.getPosition().x, turret.getPosition().z); + if (turret.getWorldPosition().getDistance2D(new Point3D(1779.27F, 12, 2517.37F))<5 || turret.getWorldPosition().getDistance2D(new Point3D(1797.00F, 12, 2518.32F))<5){ + positionY +=4; // The terrainService delivers incorrect heights on that bridge near the general in Keren + } + turret.setPosition(new Point3D(turret.getPosition().x,positionY, turret.getPosition().z)); + String customName = "Rebel Turret"; + String factionString = "rebel"; + if (getPylonFaction()==Factions.Imperial){ + customName = "Imperial Turret"; + factionString = "imperial"; + } + turret.setCustomName(customName); + + turret.setOptionsBitmask(Options.ATTACKABLE | Options.QUEST); + //turret.setOptionsBitmask(Options.QUEST); + turret.setFaction(factionString); + turret.setFactionStatus(FactionStatus.Combatant); + turret.setMaximumCondition(50000); + TurretAIActor actor = new TurretAIActor(turret, turret.getPosition(), scheduler); + turret.setAttachment("AI", actor); + NGECore.getInstance().invasionService.registerPhase2Objects(turret); + + WeaponObject turretWeapon = (WeaponObject) NGECore.getInstance().objectService.createObject("object/weapon/ranged/turret/shared_turret_heat.iff", turret.getPlanet()); + turretWeapon.setAttackSpeed(5.0F); + //turretWeapon.setAttackSpeed(0.50F); + turretWeapon.setWeaponType(WeaponType.RIFLE); + turretWeapon.setMaxRange(60.0F); + turretWeapon.setDamageType("energy"); + + int minDamage = 1500; int maxDamage = 2000; + if (spawnLevel==2) {minDamage=2500; maxDamage=3500;} + if (spawnLevel==3) {minDamage=4000; maxDamage=5000;} + + turretWeapon.setMinDamage(minDamage); + turretWeapon.setMaxDamage(maxDamage); + //turret.add(turretWeapon); // Does not have to be added explicitly, would cause engine slot arrangement error message + turret.setAttachment("TurretWeapon",turretWeapon.getObjectID()); + } + + public void createBarricade(){ + String barricadeTemplate = "object/tangible/destructible/shared_gcw_rebel_barricade.iff"; + TangibleObject barricade = (TangibleObject) NGECore.getInstance().objectService.createObject(barricadeTemplate, 0, this.getPlanet(), this.getWorldPosition(), this.getOrientation()); + NGECore.getInstance().simulationService.add(barricade, barricade.getPosition().x, barricade.getPosition().z, true); + String customName = "Rebel Barricade"; + String factionString = "rebel"; + if (getPylonFaction()==Factions.Imperial){ + customName = "Imperial Barricade"; + factionString = "imperial"; + } + barricade.setCustomName(customName); + barricade.setOptionsBitmask(Options.ATTACKABLE | Options.QUEST); + //barricade.setOptionsBitmask(Options.QUEST); + barricade.setFaction(factionString); + barricade.setFactionStatus(FactionStatus.Combatant); + int maxCondition = 50000; + maxCondition += 5000 * resourceFilling; + + barricade.setMaximumCondition(maxCondition); + NGECore.getInstance().invasionService.registerPhase2Objects(barricade); + + final Future[] fut = {null}; + fut[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().objectService.getObject(barricade.getObjectID())==null){ + Thread.yield(); + fut[0].cancel(false); + } + + Vector nearAllies = NGECore.getInstance().simulationService.getAllNearSameFactionCreatures(7,barricade.getWorldPosition(),barricade.getPlanet(),NGECore.getInstance().invasionService.getFactionName(getPylonFaction())); + for (CreatureObject ally : nearAllies){ + if (! ally.hasBuff("barricade_defender")){ + NGECore.getInstance().buffService.addBuffToCreature(ally, "barricade_defender", ally); + } else { + + } + } // towFacGuardDefenseItem + Thread.currentThread().interrupt(); + } catch (Exception e) { + System.err.println("Exception in Barricade thread " + e.getMessage()); + } + } + }, 5, 2, TimeUnit.SECONDS); + } + + public void createTower(){ + String towerTemplate = "object/tangible/destructible/shared_gcw_rebel_tower.iff"; + String factionString = "rebel"; + String towerString = "Rebel Tower"; + if (getPylonFaction()==Factions.Imperial){ + towerTemplate = "object/tangible/destructible/shared_gcw_imperial_tower.iff"; + factionString = "imperial"; + towerString = "Imperial Tower"; + } + TangibleObject tower = (TangibleObject) NGECore.getInstance().objectService.createObject(towerTemplate, 0, this.getPlanet(), this.getWorldPosition(), this.getOrientation()); + NGECore.getInstance().simulationService.add(tower, tower.getPosition().x, tower.getPosition().z, true); + tower.setCustomName(towerString); + tower.setOptionsBitmask(Options.ATTACKABLE | Options.QUEST); + //tower.setOptionsBitmask(Options.QUEST); + tower.setFaction(factionString); + tower.setFactionStatus(FactionStatus.Combatant); + int maxCondition = 50000; + maxCondition += 5000 * resourceFilling; + + tower.setMaximumCondition(maxCondition); + NGECore.getInstance().invasionService.registerPhase2Objects(tower); + + final Future[] fut = {null}; + fut[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().objectService.getObject(tower.getObjectID())==null){ + Thread.yield(); + fut[0].cancel(false); + } + + Vector nearAllies = NGECore.getInstance().simulationService.getAllNearSameFactionNPCs(500, tower); + for (CreatureObject ally : nearAllies){ + if (!ally.isPlayer()){ + if (! ally.hasBuff("tower_defender")){ + NGECore.getInstance().buffService.addBuffToCreature(ally, "tower_defender", ally); + } + } + } + Thread.currentThread().interrupt(); + } catch (Exception e) { + System.err.println("Exception in Tower thread " + e.getMessage()); + } + } + }, 5, 2, TimeUnit.SECONDS); + } + + public int getResourceFilling() { + return resourceFilling; + } + + public void setResourceFilling(int resourceFilling) { + this.resourceFilling = resourceFilling; + } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } + + public class PylonType { + + public static final int SoldierPatrol = 0; + public static final int SoldierDefense = 1; + public static final int VehiclePatrol = 2; + public static final int SiegeVehiclePatrol = 3; + public static final int Barricade = 4; + public static final int Turret = 5; + public static final int Tower = 6; + + } + /* + Soldier Patrol Pylons - Spawns a continuous stream of NPCs to aid in the battle - shown with a Helmet icon. + Vehicle Patrol Pylons - Spawns vehicles that are considerably more lethal than the Soldiers - shown with a Terminal icon. + Siege Vehicle Patrol Pylon - Spawns Rebel Hailfire Driods or Imperial AT-ATs (only spawn at a Level 3 Pylon) - shown with the same Terminal icon. + Barricade Pylon - Spawns a barricade that defends units behind it by giving them a defensive buff - shown with a Barricade icon. + Turret Pylon - Spawns an AI controlled turret that fires on enemy units - shown with a Gun Barrel or Turret Dish icon. + Tower Pylon - Spawns a watch tower that grants intelligence to nearby NPCs and offers combat missions to players - shown with a Tower icon. + */ + + public void sendBaselines(Client destination) { + if (destination != null && destination.getSession() != null) { + destination.getSession().write(getBaseline(3).getBaseline()); + destination.getSession().write(getBaseline(6).getBaseline()); + + Client parent = ((getGrandparent() == null) ? null : getGrandparent().getClient()); + + if (parent != null && destination == parent) { + destination.getSession().write(getBaseline(8).getBaseline()); + destination.getSession().write(getBaseline(9).getBaseline()); + } + + if (destination.getParent() != this) { + // The icon disappears after a few seconds, no idea why. Must be the commandString requirement + float y = -0.1F; + //float qz= 1.06535322E9F; + float qz= 99999; + //String animName = "pt_gcw_quest_rebel_barricade.prt"; + String animName = "pt_gcw_quest_imperial_patrol_2.prt"; + //String animName = "pt_reb_insignia_02.prt"; // pt_gcw_quest_imperial_patrol_2.prt + Point3D effectorPosition = new Point3D(0,y,0); + Quaternion effectorOrientation = new Quaternion(0,0,0,qz); + PlayClientEffectObjectTransformMessage lmsg = new PlayClientEffectObjectTransformMessage("appearance/" + animName,this.getObjectID(),"",effectorPosition,effectorOrientation); + //PlayClientEffectObjectMessage lmsg = new PlayClientEffectObjectMessage("appearance/" + animName, this.getObjectID(), ""); + destination.getSession().write(lmsg.serialize()); + } + } + } +} diff --git a/src/services/gcw/GCWService.java b/src/services/gcw/GCWService.java index 6a47d4cd..b82b9ac9 100644 --- a/src/services/gcw/GCWService.java +++ b/src/services/gcw/GCWService.java @@ -46,6 +46,7 @@ import org.python.google.common.collect.Multimap; import protocol.swg.GcwGroupsRsp; import protocol.swg.GcwRegionsReq; import protocol.swg.GcwRegionsRsp; +import protocol.swg.ServerNowEpochTime; import resources.common.Opcodes; import resources.common.OutOfBand; import resources.common.collidables.CollidableCircle; @@ -492,7 +493,7 @@ public class GCWService implements INetworkDispatch { /* Ported from javascript. * Written for us by Hendrik of http://swg.activeframe.de. */ - private double helper(int points, int rank) { + public double helper(int points, int rank) { int faktor = points / (MOD2[rank-1] - 250 * rank); int rt = points / (1 + faktor) - DECAY1[rank-1]; @@ -636,9 +637,22 @@ public class GCWService implements INetworkDispatch { c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); - return (int) ((c.getTimeInMillis() - now.getTime()) / 1000L); + // Theory:Due to the client refusing the ServerNowEpochTime packet, the client assumes an epoch time of 0 for GCW! + // An alternative theory would be that the GCWTime is independent from the ServerNowEpochTime + // 2nd theory more likely, because manually sending ServerNowEpochTime (confirmed by sniff) does nothing to the GCW time + // Conclusion: GCW epoch time is set independently somehow + + // The return value must be relative to epoch of 0, the client assumes 25.12.2011 current time/date + //return (int) ((c.getTimeInMillis() - now.getTime()) / 1000L); + return (int) (1324047960 + ((c.getTimeInMillis() - now.getTime()) / 1000L)); } + public void sendServerNowEpochTime(CreatureObject player){ + + ServerNowEpochTime time = new ServerNowEpochTime((int) (System.currentTimeMillis() / 1000)); + player.getClient().getSession().write(time.serialize()); + } + public void updateNextUpdateTime() { ODBCursor cursor = core.getSWGObjectODB().getCursor(); diff --git a/src/services/gcw/GCWSpawner.java b/src/services/gcw/GCWSpawner.java new file mode 100644 index 00000000..42d4c8d8 --- /dev/null +++ b/src/services/gcw/GCWSpawner.java @@ -0,0 +1,852 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.gcw; + +import java.util.Random; +import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import main.NGECore; +import resources.datatables.Factions; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; + +/** + * @author Charon + */ + +@SuppressWarnings("unused") +public class GCWSpawner extends TangibleObject{ + + private static final long serialVersionUID = 1L; + private int spawnerType = 0; + private int spawnerFaction = 0; + private int spawnLevel = 0; + private int totalSpawnedUnits = 0; + private String[] soldierTemplates = new String[]{""}; + private String[] rebelSoldierTemplates1 = new String[]{""}; + private String[] rebelSoldierTemplates2 = new String[]{""}; + private String[] rebelSoldierTemplates3 = new String[]{"gcw_city_rebel_soldier"}; + private String[] imperialSoldierTemplates1 = new String[]{""}; + private String[] imperialSoldierTemplates2 = new String[]{""}; + private String[] imperialSoldierTemplates3 = new String[]{"elite_imperial_stormtrooper_90"}; + + private String[] vehicleTemplates = new String[]{""}; + private String[] rebelVehicleTemplates1 = new String[]{"rebel_invasion_at_xt"}; + private String[] rebelVehicleTemplates2 = new String[]{"rebel_invasion_at_xt"}; + private String[] rebelVehicleTemplates3 = new String[]{"rebel_invasion_at_xt"}; + private String[] imperialVehicleTemplates1 = new String[]{"imp_invasion_at_st"}; + private String[] imperialVehicleTemplates2 = new String[]{"imp_invasion_at_st"}; + private String[] imperialVehicleTemplates3 = new String[]{"imp_invasion_at_st"}; + + + private String[] siegeVehicleTemplates = new String[]{""}; + private String[] rebelSiegeVehicleTemplates1 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] rebelSiegeVehicleTemplates2 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] rebelSiegeVehicleTemplates3 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] imperialSiegeVehicleTemplates1 = new String[]{"imp_invasion_at_at"}; + private String[] imperialSiegeVehicleTemplates2 = new String[]{"imp_invasion_at_at"}; + private String[] imperialSiegeVehicleTemplates3 = new String[]{"imp_invasion_at_at"}; + + private String barricadeTemplate = ""; + private String rebelBarricadeTemplate = "object/tangible/destructible/shared_gcw_rebel_barricade.iff"; + private String imperialBarricadeTemplate = "object/tangible/destructible/shared_gcw_imperial_barricade.iff"; + + + private String turretTemplates = ""; + private String[] rebelTurretTemplates1 = new String[]{""}; + private String[] rebelTurretTemplates2 = new String[]{""}; + private String[] rebelTurretTemplates3 = new String[]{"object/tangible/destructible/shared_gcw_rebel_turret.iff"}; + private String[] imperialTurretTemplates1 = new String[]{""}; + private String[] imperialTurretTemplates2 = new String[]{""}; + private String[] imperialTurretTemplates3 = new String[]{"object/tangible/destructible/shared_gcw_imperial_turret.iff"}; + + private String towerTemplate = ""; + private String rebelTowerTemplate = "object/tangible/destructible/shared_gcw_rebel_tower.iff"; + private String imperialTowerTemplate = "object/tangible/destructible/shared_gcw_imperial_tower.iff"; + + private Vector patrolRoute = new Vector(); + private CreatureObject lastDefender = null; + private int delay = 0; + + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public GCWSpawner() { + super(); + } + + public GCWSpawner(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ + super(objectID, planet, position, orientation, template); + } + + public int getSpawnerType() { + return spawnerType; + } + + public void setSpawnerType(int spawnerType) { + this.spawnerType = spawnerType; + this.setCustomName(""); + if (spawnerType==SpawnerType.SoldierPatrol){ + final Future[] fut1 = {null}; + fut1[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().invasionService.getInvasionPhase()>2){ + Thread.yield(); + fut1[0].cancel(false); + } + spawnSoldier(); + } catch (Exception e) { + System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnSoldier() " + e.getMessage()); + } + } + }, getDelay(), 240, TimeUnit.SECONDS); //120 + } + + if (spawnerType==SpawnerType.SoldierDefense){ + final Future[] fut2 = {null}; + fut2[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().invasionService.getInvasionPhase()>2){ + Thread.yield(); + fut2[0].cancel(false); + } + spawnSoldierDefender(); + } catch (Exception e) { + System.err.println("Exception in SoldierDefensePylon->scheduleAtFixedRate->spawnSoldier() " + e.getMessage()); + } + } + }, 5, 90, TimeUnit.SECONDS); + } + + if (spawnerType==SpawnerType.VehiclePatrol){ + final Future[] fut3 = {null}; + fut3[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().invasionService.getInvasionPhase()>2){ + Thread.yield(); + fut3[0].cancel(false); + } + spawnVehicle(); + } catch (Exception e) { + System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnVehicle() " + e.getMessage()); + } + } + }, getDelay(), 240, TimeUnit.SECONDS); //240 + } + + if (spawnerType==SpawnerType.SiegeVehiclePatrol){ + final Future[] fut4 = {null}; + fut4[0] = scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + if (NGECore.getInstance().invasionService.getInvasionPhase()>2){ + Thread.yield(); + fut4[0].cancel(false); + } + spawnSiegeVehicle(); + } catch (Exception e) { + System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnSoldier() " + e.getMessage()); + } + } + }, getDelay(), 600, TimeUnit.SECONDS); + } + + } + + public int getSpawnerFaction() { + return spawnerFaction; + } + + public void setSpawnerFaction(int spawnerFaction) { + this.spawnerFaction = spawnerFaction; + } + + public int getSpawnLevel() { + return spawnLevel; + } + + public void setSpawnLevel(int spawnLevel) { + this.spawnLevel = spawnLevel; + } + + public void spawnSoldier(){ + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + String stfName = "gcw_city_rebel_specforce_defense"; + if (spawnerFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: soldierTemplates = rebelSoldierTemplates1; + stfName = "gcw_city_rebel_grunt_assault"; + break; + case 2: soldierTemplates = rebelSoldierTemplates2; + stfName = "gcw_city_rebel_grunt_assault"; + break; + case 3: soldierTemplates = rebelSoldierTemplates3; + stfName = "gcw_city_rebel_specforce_assault"; + break; + } + } + if (spawnerFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: soldierTemplates = imperialSoldierTemplates1; + break; + case 2: soldierTemplates = imperialSoldierTemplates2; + break; + case 3: soldierTemplates = imperialSoldierTemplates3; + break; + } + } + String soldierTemplate = soldierTemplates[new Random().nextInt(soldierTemplates.length)]; + //if (totalSpawnedUnits==0){ + CreatureObject soldier = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(soldierTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + if (spawnerFaction==Factions.Rebel) + soldier.setStfName(stfName); + if (spawnerFaction==Factions.Imperial){ + String[] Prefices = new String[]{"GK-","TK-"}; + int suffix = 300 + new Random().nextInt(700); + String stormtrooperID = Prefices[new Random().nextInt(Prefices.length)]+suffix; + soldier.setCustomName(stormtrooperID); + } + NGECore.getInstance().invasionService.registerInvader(soldier); + totalSpawnedUnits++; + soldier.setAttachment("IsInvader","yes"); + NGECore.getInstance().aiService.setPatrol(soldier, patrolRoute); + NGECore.getInstance().aiService.setPatrolLoop(soldier,false); + + //} + } + } + + public void spawnSoldierDefender(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + String stfName = "gcw_city_rebel_specforce_defense"; + if (spawnerFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: soldierTemplates = rebelSoldierTemplates1; + stfName = "gcw_city_rebel_grunt_defense"; + break; + case 2: soldierTemplates = rebelSoldierTemplates2; + stfName = "gcw_city_rebel_grunt_defense"; + break; + case 3: soldierTemplates = rebelSoldierTemplates3; + stfName = "gcw_city_rebel_specforce_defense"; + break; + } + } + if (spawnerFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: soldierTemplates = imperialSoldierTemplates1; + break; + case 2: soldierTemplates = imperialSoldierTemplates2; + break; + case 3: soldierTemplates = imperialSoldierTemplates3; + break; + } + } + if (lastDefender!=null) + if (lastDefender.getPosture()!=13 && lastDefender.getPosture()!=13) + return; + String soldierTemplate = soldierTemplates[new Random().nextInt(soldierTemplates.length)]; + lastDefender = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(soldierTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + if (spawnerFaction==Factions.Rebel) + lastDefender.setStfName(stfName); + if (spawnerFaction==Factions.Imperial){ + String[] Prefices = new String[]{"GK-","TK-"}; + int suffix = 300 + new Random().nextInt(700); + String stormtrooperID = Prefices[new Random().nextInt(Prefices.length)]+suffix; + lastDefender.setCustomName(stormtrooperID); + } + NGECore.getInstance().invasionService.registerDefender(lastDefender); + totalSpawnedUnits++; + } + } + + public void spawnVehicle(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + if (spawnerFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: vehicleTemplates = rebelVehicleTemplates1; + case 2: vehicleTemplates = rebelVehicleTemplates2; + case 3: vehicleTemplates = rebelVehicleTemplates3; + } + } + if (spawnerFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: vehicleTemplates = imperialVehicleTemplates1; + case 2: vehicleTemplates = imperialVehicleTemplates2; + case 3: vehicleTemplates = imperialVehicleTemplates3; + } + } + String vehicleTemplate = vehicleTemplates[new Random().nextInt(vehicleTemplates.length)]; + CreatureObject vehicle = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(vehicleTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + NGECore.getInstance().invasionService.registerInvader(vehicle); + totalSpawnedUnits++; + vehicle.setAttachment("IsInvader","yes"); + NGECore.getInstance().aiService.setPatrol(vehicle, patrolRoute); + NGECore.getInstance().aiService.setPatrolLoop(vehicle,false); + } + } + + public void spawnSiegeVehicle(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + if (spawnerFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: vehicleTemplates = rebelSiegeVehicleTemplates1; + case 2: vehicleTemplates = rebelSiegeVehicleTemplates2; + case 3: vehicleTemplates = rebelSiegeVehicleTemplates3; + } + } + if (spawnerFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: vehicleTemplates = imperialSiegeVehicleTemplates1; + case 2: vehicleTemplates = imperialSiegeVehicleTemplates2; + case 3: vehicleTemplates = imperialSiegeVehicleTemplates3; + } + } + String vehicleTemplate = vehicleTemplates[new Random().nextInt(vehicleTemplates.length)]; + CreatureObject vehicle = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(vehicleTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + vehicle.setAttachment("IsSlowVehicle",true); + NGECore.getInstance().invasionService.registerInvader(vehicle); + totalSpawnedUnits++; + vehicle.setAttachment("IsInvader","yes"); + + NGECore.getInstance().aiService.setPatrol(vehicle, patrolRoute); + NGECore.getInstance().aiService.setPatrolLoop(vehicle,false); + } + } + + public void setPatrolRoute(int route){ + switch(route){ + case PatrolRoute.Dearic1: patrolRoute = get_Dearic_Route_1(); + break; + case PatrolRoute.Dearic2: patrolRoute = get_Dearic_Route_2(); + break; + case PatrolRoute.Dearic3: patrolRoute = get_Dearic_Route_3(); + break; + case PatrolRoute.Dearic4: patrolRoute = get_Dearic_Route_4(); + break; + case PatrolRoute.Dearic5: patrolRoute = get_Dearic_Route_5(); + break; + case PatrolRoute.Dearic6: patrolRoute = get_Dearic_Route_6(); + break; + case PatrolRoute.Dearic7: patrolRoute = get_Dearic_Route_7(); + break; + case PatrolRoute.Dearic8: patrolRoute = get_Dearic_Route_8(); + break; + case PatrolRoute.Dearic9: patrolRoute = get_Dearic_Route_9(); + break; + case PatrolRoute.Dearic10: patrolRoute = get_Dearic_Route_10(); + break; + case PatrolRoute.Dearic11: patrolRoute = get_Dearic_Route_11(); + break; + + case PatrolRoute.Keren1: patrolRoute = get_Keren_Route_1(); + break; + case PatrolRoute.Keren2: patrolRoute = get_Keren_Route_2(); + break; + case PatrolRoute.Keren3: patrolRoute = get_Keren_Route_3(); + break; + case PatrolRoute.Keren4: patrolRoute = get_Keren_Route_4(); + break; + case PatrolRoute.Keren5: patrolRoute = get_Keren_Route_5(); + break; + case PatrolRoute.Keren6: patrolRoute = get_Keren_Route_6(); + break; + case PatrolRoute.Keren7: patrolRoute = get_Keren_Route_7(); + break; + + case PatrolRoute.Bestine1: patrolRoute = get_Bestine_Route_1(); + break; + case PatrolRoute.Bestine2: patrolRoute = get_Bestine_Route_2(); + break; + case PatrolRoute.Bestine3: patrolRoute = get_Bestine_Route_3(); + break; + case PatrolRoute.Bestine4: patrolRoute = get_Bestine_Route_4(); + break; + case PatrolRoute.Bestine5: patrolRoute = get_Bestine_Route_5(); + break; + case PatrolRoute.Bestine6: patrolRoute = get_Bestine_Route_6(); + break; + case PatrolRoute.Bestine7: patrolRoute = get_Bestine_Route_7(); + break; + case PatrolRoute.Bestine8: patrolRoute = get_Bestine_Route_8(); + break; + } + } + + public Vector get_Dearic_Route_1(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(68.0F, 6.00F, -2959F)); + patrolpoints.add(new Point3D(151.93F,6.00F, -2961.66F)); + patrolpoints.add(new Point3D(170.18F, 6.00F, -2992.99F)); + patrolpoints.add(new Point3D(262.76F, 6.00F, -2999.76F)); + patrolpoints.add(new Point3D(275.87F, 6.00F, -3008.44F)); + patrolpoints.add(new Point3D(303.41F, 6.00F, -3005.19F)); + patrolpoints.add(new Point3D(343.31F, 6.00F, -2961.06F)); + patrolpoints.add(new Point3D(379.98F, 6.00F, -2963.31F)); + patrolpoints.add(new Point3D(404.70F, 6.00F, -2980.57F)); + patrolpoints.add(new Point3D(412.54F, 6.00F, -3039.39F)); + patrolpoints.add(new Point3D(423.06F, 6.00F, -3050.75F)); + patrolpoints.add(new Point3D(446.92F, 6.00F, -3046.32F)); + patrolpoints.add(new Point3D(470.48F, 6.00F, -3023.43F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_2(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(76.0F, 6.00F, -2893F)); + patrolpoints.add(new Point3D(153.0F, 6.00F, -2898F)); + patrolpoints.add(new Point3D(162.89F, 6.00F, -2836.9F)); + patrolpoints.add(new Point3D(291.44F, 6.00F, -2844.6F)); + patrolpoints.add(new Point3D(333.19F, 6.00F, -2878.0F)); + patrolpoints.add(new Point3D(337.00F, 6.00F, -2954.0F)); + patrolpoints.add(new Point3D(378.00F, 6.00F, -2959.0F)); + patrolpoints.add(new Point3D(407.00F, 6.00F, -2978.0F)); + patrolpoints.add(new Point3D(414.00F, 6.00F, -3041.0F)); + patrolpoints.add(new Point3D(448.00F, 6.00F, -3043.0F)); + patrolpoints.add(new Point3D(464.00F, 6.00F, -3017.0F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_3(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(199.0F, 6.00F, -2790F)); + patrolpoints.add(new Point3D(200.0F, 6.00F, -2838F)); + patrolpoints.add(new Point3D(294.0F, 6.00F, -2841F)); + patrolpoints.add(new Point3D(335.0F, 6.00F, -2882F)); + patrolpoints.add(new Point3D(341.0F, 6.00F, -2950F)); + patrolpoints.add(new Point3D(378.0F, 6.00F, -2958F)); + patrolpoints.add(new Point3D(405.0F, 6.00F, -2981F)); + patrolpoints.add(new Point3D(414.00F, 6.00F, -3041.0F)); + patrolpoints.add(new Point3D(448.00F, 6.00F, -3043.0F)); + patrolpoints.add(new Point3D(473.0F, 6.00F, -3024F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_4(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(332.0F, 6.00F, -2715F)); + patrolpoints.add(new Point3D(324.0F, 6.00F, -2817F)); + patrolpoints.add(new Point3D(302.0F, 6.00F, -2835F)); + patrolpoints.add(new Point3D(338.0F, 6.00F, -2888F)); + patrolpoints.add(new Point3D(342.0F, 6.00F, -2949F)); + patrolpoints.add(new Point3D(407.0F, 6.00F, -2972F)); + patrolpoints.add(new Point3D(415.0F, 6.00F, -3055F)); + patrolpoints.add(new Point3D(451.0F, 6.00F, -3044F)); + patrolpoints.add(new Point3D(460.0F, 6.00F, -3011F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_5(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2720F)); + patrolpoints.add(new Point3D(404.0F, 6.00F, -2817F)); + patrolpoints.add(new Point3D(417.0F, 6.00F, -2827F)); + patrolpoints.add(new Point3D(414.0F, 6.00F, -2854F)); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2888F)); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2959F)); + patrolpoints.add(new Point3D(407.0F, 6.00F, -2975F)); + patrolpoints.add(new Point3D(416.0F, 6.00F, -3049F)); + patrolpoints.add(new Point3D(450.0F, 6.00F, -3043F)); + patrolpoints.add(new Point3D(474.0F, 6.00F, -3025F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_6(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(590.0F, 6.00F, -2825F)); + patrolpoints.add(new Point3D(567.0F, 6.00F, -2860F)); + patrolpoints.add(new Point3D(563.0F, 6.00F, -2943F)); + patrolpoints.add(new Point3D(563.0F, 6.00F, -2943F)); + patrolpoints.add(new Point3D(507.0F, 6.00F, -2955F)); + patrolpoints.add(new Point3D(500.0F, 6.00F, -3011F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_7(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(723.0F, 6.00F, -2995F)); + patrolpoints.add(new Point3D(720.0F, 6.00F, -2964F)); + patrolpoints.add(new Point3D(623.0F, 6.00F, -2961F)); + patrolpoints.add(new Point3D(614.0F, 6.00F, -3010F)); + patrolpoints.add(new Point3D(510.0F, 6.00F, -3032F)); + patrolpoints.add(new Point3D(484.0F, 6.00F, -3021F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_8(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(733.0F, 6.00F, -3004F)); + patrolpoints.add(new Point3D(701.0F, 6.00F, -3004F)); + patrolpoints.add(new Point3D(699.0F, 6.00F, -3039F)); + patrolpoints.add(new Point3D(627.0F, 6.00F, -3041F)); + patrolpoints.add(new Point3D(605.0F, 6.00F, -3018F)); + patrolpoints.add(new Point3D(509.0F, 6.00F, -3033F)); + patrolpoints.add(new Point3D(495.0F, 6.00F, -3017F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_9(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(330.0F, 23.00F, -3402F)); + patrolpoints.add(new Point3D(360.0F, 6.00F, -3357F)); + patrolpoints.add(new Point3D(415.0F, 6.00F, -3273F)); + patrolpoints.add(new Point3D(464.0F, 6.00F, -3256F)); + patrolpoints.add(new Point3D(467.0F, 6.00F, -3236F)); + patrolpoints.add(new Point3D(498.0F, 6.00F, -3230F)); + patrolpoints.add(new Point3D(501.0F, 6.00F, -3205F)); + patrolpoints.add(new Point3D(481.0F, 6.00F, -3174F)); + patrolpoints.add(new Point3D(482.0F, 6.00F, -3126F)); + patrolpoints.add(new Point3D(437.0F, 6.00F, -3065F)); + patrolpoints.add(new Point3D(465.0F, 6.00F, -3019F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_10(){// just for tests + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(618.0F, 6.00F, -2972F)); + patrolpoints.add(new Point3D(617.0F, 6.00F, -2980F)); + patrolpoints.add(new Point3D(616.0F, 6.00F, -2990F)); + patrolpoints.add(new Point3D(615.0F, 6.00F, -3010F)); + patrolpoints.add(new Point3D(500.0F, 6.00F, -3035F)); + + return patrolpoints; + } + + public Vector get_Dearic_Route_11(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(332.0F, 6.00F, -2715F)); + return patrolpoints; + } + + + public Vector get_Keren_Route_1(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1342.0F, 13.00F, 2917F)); + patrolpoints.add(new Point3D(1447.0F, 13.00F, 2825F)); + patrolpoints.add(new Point3D(1463.0F, 14.00F, 2781F)); + patrolpoints.add(new Point3D(1530.0F, 25.00F, 2760F)); + patrolpoints.add(new Point3D(1523.0F, 25.00F, 2731F)); + patrolpoints.add(new Point3D(1555.0F, 29.00F, 2721F)); + patrolpoints.add(new Point3D(1607.0F, 25.00F, 2706F)); + patrolpoints.add(new Point3D(1607.0F, 25.00F, 2706F)); + patrolpoints.add(new Point3D(1601.0F, 25.00F, 2676F)); + patrolpoints.add(new Point3D(1652.0F, 12.00F, 2652F)); + patrolpoints.add(new Point3D(1674.0F, 12.00F, 2637F)); + patrolpoints.add(new Point3D(1674.0F, 12.00F, 2586F)); + patrolpoints.add(new Point3D(1725.0F, 12.00F, 2584F)); + patrolpoints.add(new Point3D(1727.0F, 12.00F, 2559F)); + patrolpoints.add(new Point3D(1758.0F, 12.00F, 2555F)); + patrolpoints.add(new Point3D(1766.0F, 12.00F, 2528F)); + patrolpoints.add(new Point3D(1780.0F, 12.00F, 2520F)); + return patrolpoints; + } + + public Vector get_Keren_Route_2(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1994.03F, 12.00F, 2769.94F)); + patrolpoints.add(new Point3D(1981.79F, 13.89F, 2736.23F)); + patrolpoints.add(new Point3D(1911.87F, 12F, 2737.51F)); + patrolpoints.add(new Point3D(1892.03F, 12F, 2718.64F)); + patrolpoints.add(new Point3D(1883.43F, 12F, 2727.32F)); + patrolpoints.add(new Point3D(1863.00F, 12F, 2707.36F)); + patrolpoints.add(new Point3D(1883.67F, 12F, 2694.01F)); + patrolpoints.add(new Point3D(1899.48F, 12F, 2661.86F)); + patrolpoints.add(new Point3D(1901.68F, 12F, 2638.95F)); + patrolpoints.add(new Point3D(1897.24F, 12F, 2603.49F)); + patrolpoints.add(new Point3D(1879.39F, 12F, 2563.75F)); + patrolpoints.add(new Point3D(1841.89F, 12F, 2527.75F)); + patrolpoints.add(new Point3D(1824.33F, 12F, 2521.45F)); + patrolpoints.add(new Point3D(1789.56F, 12F, 2518.26F)); + + return patrolpoints; + } + + public Vector get_Keren_Route_3(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(2063.0F, 49.00F, 2794F)); + patrolpoints.add(new Point3D(2020.0F, 49.00F, 2796F)); + patrolpoints.add(new Point3D(1817.0F, 40.00F, 2808F)); + patrolpoints.add(new Point3D(1753.0F, 40.00F, 2808F)); + patrolpoints.add(new Point3D(1715.0F, 40.00F, 2780F)); + patrolpoints.add(new Point3D(1717.0F, 12.00F, 2741F)); + patrolpoints.add(new Point3D(1713.0F, 12.00F, 2639F)); + patrolpoints.add(new Point3D(1695.0F, 12.00F, 2635F)); + patrolpoints.add(new Point3D(1696.0F, 12.00F, 2589F)); + patrolpoints.add(new Point3D(1725.0F, 12.00F, 2585F)); + patrolpoints.add(new Point3D(1727.0F, 12.00F, 2560F)); + patrolpoints.add(new Point3D(1758.0F, 12.00F, 2555F)); + patrolpoints.add(new Point3D(1766.0F, 12.00F, 2527F)); + patrolpoints.add(new Point3D(1781.0F, 12.00F, 2516F)); + + return patrolpoints; + } + + public Vector get_Keren_Route_4(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1990.0F, 30.00F, 2715F)); + patrolpoints.add(new Point3D(1990.0F, 30.00F, 2682F)); + patrolpoints.add(new Point3D(1988.0F, 12.00F, 2624F)); + patrolpoints.add(new Point3D(1983.0F, 12.00F, 2560F)); + patrolpoints.add(new Point3D(1931.0F, 12.00F, 2535F)); + patrolpoints.add(new Point3D(1902.0F, 12.00F, 2554F)); + patrolpoints.add(new Point3D(1879.0F, 12.00F, 2525F)); + patrolpoints.add(new Point3D(1846.0F, 12.00F, 2504F)); + patrolpoints.add(new Point3D(1806.0F, 12.00F, 2492F)); + patrolpoints.add(new Point3D(1806.0F, 12.00F, 2520F)); + patrolpoints.add(new Point3D(1794.0F, 12.00F, 2519F)); + + return patrolpoints; + } + + public Vector get_Keren_Route_5(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1342.0F, 13.00F, 2917F)); + patrolpoints.add(new Point3D(1447.0F, 13.00F, 2825F)); + patrolpoints.add(new Point3D(1463.0F, 14.00F, 2781F)); + patrolpoints.add(new Point3D(1530.0F, 25.00F, 2760F)); + patrolpoints.add(new Point3D(1523.0F, 25.00F, 2731F)); + patrolpoints.add(new Point3D(1555.0F, 29.00F, 2721F)); + patrolpoints.add(new Point3D(1607.0F, 25.00F, 2706F)); + patrolpoints.add(new Point3D(1607.0F, 25.00F, 2706F)); + patrolpoints.add(new Point3D(1601.0F, 25.00F, 2676F)); + patrolpoints.add(new Point3D(1652.0F, 12.00F, 2652F)); + patrolpoints.add(new Point3D(1674.0F, 12.00F, 2637F)); + patrolpoints.add(new Point3D(1674.0F, 12.00F, 2586F)); + patrolpoints.add(new Point3D(1725.0F, 12.00F, 2584F)); + patrolpoints.add(new Point3D(1758.0F, 12.00F, 2555F)); + patrolpoints.add(new Point3D(1766.0F, 12.00F, 2528F)); + patrolpoints.add(new Point3D(1780.0F, 12.00F, 2520F)); + return patrolpoints; + } + + public Vector get_Keren_Route_6(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1980.0F, 10.00F, 2179F)); + patrolpoints.add(new Point3D(1957.0F, 11.00F, 2259F)); + patrolpoints.add(new Point3D(1934.0F, 12.00F, 2341F)); + patrolpoints.add(new Point3D(1947.0F, 12.00F, 2387F)); + patrolpoints.add(new Point3D(1945.0F, 12.00F, 2414F)); + patrolpoints.add(new Point3D(1879.0F, 12.00F, 2419F)); + patrolpoints.add(new Point3D(1847.0F, 12.00F, 2458F)); + patrolpoints.add(new Point3D(1789.0F, 12.00F, 2459F)); + patrolpoints.add(new Point3D(1743.0F, 12.00F, 2458F)); + patrolpoints.add(new Point3D(1728.0F, 12.00F, 2468F)); + patrolpoints.add(new Point3D(1729.0F, 12.00F, 2495F)); + patrolpoints.add(new Point3D(1761.0F, 12.00F, 2495F)); + patrolpoints.add(new Point3D(1764.0F, 12.00F, 2516F)); + patrolpoints.add(new Point3D(1776.0F, 12.00F, 2517F)); + return patrolpoints; + } + + public Vector get_Keren_Route_7(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(1342.0F, 13.00F, 2917F)); + patrolpoints.add(new Point3D(1487.0F, 20.00F, 2808F)); + + return patrolpoints; + } + + public Vector get_Bestine_Route_1(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-978.75F, 12.00F, -3747.46F)); + patrolpoints.add(new Point3D(-996.37F, 12.00F, -3731.11F)); + patrolpoints.add(new Point3D(-1004.13F, 12.00F, -3708.60F)); + patrolpoints.add(new Point3D(-1042.40F, 12.00F, -3672.19F)); + patrolpoints.add(new Point3D(-1067.11F, 12.00F, -3665.97F)); + patrolpoints.add(new Point3D(-1107.36F, 12.00F, -3633.51F)); + patrolpoints.add(new Point3D(-1126.32F, 12.00F, -3650.40F)); + patrolpoints.add(new Point3D(-1144.03F, 12.00F, -3652.36F)); + patrolpoints.add(new Point3D(-1175.46F, 12.00F, -3631.40F)); + patrolpoints.add(new Point3D(-1204.07F, 12.00F, -3627.40F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_2(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1002.90F, 19.15F, -3593.77F)); + patrolpoints.add(new Point3D(-1053.93F, 12F, -3576.39F)); + patrolpoints.add(new Point3D(-1064.00F, 12F, -3586.90F)); + patrolpoints.add(new Point3D(-1084.30F, 12F, -3583.85F)); + patrolpoints.add(new Point3D(-1100.69F, 12F, -3622.65F)); + patrolpoints.add(new Point3D(-1129.25F, 12F, -3653.48F)); + patrolpoints.add(new Point3D(-1158.12F, 12F, -3654.10F)); + patrolpoints.add(new Point3D(-1191.37F, 12F, -3628.60F)); + patrolpoints.add(new Point3D(-1214.79F, 12F, -3633.39F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_3(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1104F, 20.00F, -3467F)); + patrolpoints.add(new Point3D(-1084.21F, 12.00F, -3513.44F)); + patrolpoints.add(new Point3D(-1107.65F, 12.00F, -3570.01F)); + patrolpoints.add(new Point3D(-1166.30F, 12.00F, -3527.04F)); + patrolpoints.add(new Point3D(-1182.49F, 12.00F, -3543.62F)); + patrolpoints.add(new Point3D(-1195.03F, 12.00F, -3534.84F)); + patrolpoints.add(new Point3D(-1222.08F, 12.00F, -3567.95F)); + patrolpoints.add(new Point3D(-1245.74F, 12.00F, -3550.56F)); + patrolpoints.add(new Point3D(-1284.93F, 12.00F, -3596.65F)); + patrolpoints.add(new Point3D(-1255.27F, 12.00F, -3620.79F)); + patrolpoints.add(new Point3D(-1223.85F, 12.00F, -3625.50F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_4(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1224.17F, 14.92F, -3477.66F)); + patrolpoints.add(new Point3D(-1214.17F, 12F, -3520.83F)); + patrolpoints.add(new Point3D(-1239.38F, 12F, -3552.16F)); + patrolpoints.add(new Point3D(-1251.67F, 12F, -3554.41F)); + patrolpoints.add(new Point3D(-1288.84F, 12F, -3605.51F)); + patrolpoints.add(new Point3D(-1253.18F, 12F, -3620.50F)); + patrolpoints.add(new Point3D(-1224.78F, 12F, -3627.92F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_5(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1289.09F, 10.77F, -3451.00F)); + patrolpoints.add(new Point3D(-1287.35F, 12F, -3499.91F)); + patrolpoints.add(new Point3D(-1293.84F, 12F, -3516.75F)); + patrolpoints.add(new Point3D(-1293.84F, 12F, -3516.75F)); + patrolpoints.add(new Point3D(-1282.01F, 12F, -3531.76F)); + patrolpoints.add(new Point3D(-1286.69F, 12F, -3604.70F)); + patrolpoints.add(new Point3D(-1247.24F, 12F, -3622.33F)); + patrolpoints.add(new Point3D(-1221.27F, 12F, -3616.53F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_6(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1399.33F, 18.02F, -3842.45F)); + patrolpoints.add(new Point3D(-1378.02F, 10.02F, -3803.54F)); + patrolpoints.add(new Point3D(-1355.98F, 12.25F, -3741.07F)); + patrolpoints.add(new Point3D(-1351.22F, 12.0F, -3703.81F)); + patrolpoints.add(new Point3D(-1301.95F, 12.0F, -3626.74F)); + patrolpoints.add(new Point3D(-1261.14F, 12.0F, -3624.71F)); + patrolpoints.add(new Point3D(-1224.89F, 12.0F, -3631.51F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_7(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1319.14F, 21.54F, -3854.52F)); + patrolpoints.add(new Point3D(-1327.96F, 24.39F, -3791.74F)); + patrolpoints.add(new Point3D(-1325.62F, 12.0F, -3694.68F)); + patrolpoints.add(new Point3D(-1325.62F, 12.0F, -3694.68F)); + patrolpoints.add(new Point3D(-1313.86F, 12.0F, -3632.90F)); + patrolpoints.add(new Point3D(-1261.17F, 12.0F, -3623.71F)); + patrolpoints.add(new Point3D(-1225.88F, 12.0F, -3631.15F)); + return patrolpoints; + } + + public Vector get_Bestine_Route_8(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(-1143.05F, 14.43F, -3756.47F)); + patrolpoints.add(new Point3D(-1126.50F, 12F, -3691.73F)); + patrolpoints.add(new Point3D(-1188.91F, 12F, -3627.55F)); + patrolpoints.add(new Point3D(-1203.55F, 12F, -3624.19F)); + return patrolpoints; + } + + + public int getTotalSpawnedUnits() { + return totalSpawnedUnits; + } + + public void setTotalSpawnedUnits(int totalSpawnedUnits) { + this.totalSpawnedUnits = totalSpawnedUnits; + } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } + + public class SpawnerType { + + public static final int SoldierPatrol = 0; + public static final int SoldierDefense = 1; + public static final int VehiclePatrol = 2; + public static final int SiegeVehiclePatrol = 3; + public static final int Barricade = 4; + public static final int Turret = 5; + public static final int Tower = 6; + + } + /* + Soldier Patrol Pylons - Spawns a continuous stream of NPCs to aid in the battle - shown with a Helmet icon. + Vehicle Patrol Pylons - Spawns vehicles that are considerably more lethal than the Soldiers - shown with a Terminal icon. + Siege Vehicle Patrol Pylon - Spawns Rebel Hailfire Driods or Imperial AT-ATs (only spawn at a Level 3 Pylon) - shown with the same Terminal icon. + Barricade Pylon - Spawns a barricade that defends units behind it by giving them a defensive buff - shown with a Barricade icon. + Turret Pylon - Spawns an AI controlled turret that fires on enemy units - shown with a Gun Barrel or Turret Dish icon. + Tower Pylon - Spawns a watch tower that grants intelligence to nearby NPCs and offers combat missions to players - shown with a Tower icon. + */ + + public class PatrolRoute { + + public static final int Dearic1 = 0; + public static final int Dearic2 = 1; + public static final int Dearic3 = 2; + public static final int Dearic4 = 3; + public static final int Dearic5 = 4; + public static final int Dearic6 = 5; + public static final int Dearic7 = 6; + public static final int Dearic8 = 7; + public static final int Dearic9 = 8; + public static final int Dearic10 = 9; + public static final int Dearic11 = 10; + + public static final int Keren1 = 11; + public static final int Keren2 = 12; + public static final int Keren3 = 13; + public static final int Keren4 = 14; + public static final int Keren5 = 15; + public static final int Keren6 = 16; + public static final int Keren7 = 17; + + public static final int Bestine1 = 18; + public static final int Bestine2 = 19; + public static final int Bestine3 = 20; + public static final int Bestine4 = 21; + public static final int Bestine5 = 22; + public static final int Bestine6 = 23; + public static final int Bestine7 = 24; + public static final int Bestine8 = 25; + public static final int Bestine9 = 26; + } +} diff --git a/src/services/gcw/InvasionService.java b/src/services/gcw/InvasionService.java new file mode 100644 index 00000000..8f61c15d --- /dev/null +++ b/src/services/gcw/InvasionService.java @@ -0,0 +1,2438 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.gcw; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.mina.core.session.IoSession; + +import protocol.swg.CommPlayerMessage; +import protocol.swg.ObjControllerMessage; +import protocol.swg.PlayClientEffectObjectTransformMessage; +import protocol.swg.objectControllerObjects.NpcConversationMessage; +import protocol.swg.objectControllerObjects.QuestTaskTimerMessage; +import resources.common.OutOfBand; +import resources.common.SpawnPoint; +import resources.datatables.FactionStatus; +import resources.datatables.Factions; +import resources.datatables.GalaxyStatus; +import resources.datatables.GcwType; +import resources.datatables.Options; +import resources.datatables.Posture; +import resources.objects.building.BuildingObject; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import services.ai.AIActor; +import services.ai.states.AIState; +import services.ai.states.DeathState; +import services.ai.states.WithdrawalState; +import services.gcw.GCWSpawner.PatrolRoute; +import services.gcw.GCWPylon.PylonType; +import services.sui.SUIWindow; +import services.sui.SUIService.ListBoxType; +import services.sui.SUIWindow.SUICallback; +import services.sui.SUIWindow.Trigger; +import main.NGECore; +import engine.clients.Client; +import engine.resources.common.CRC; +import engine.resources.config.Config; +import engine.resources.container.Traverser; +import engine.resources.objects.SWGObject; +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +/** + * @author Charon + */ + +@SuppressWarnings("unused") +public class InvasionService implements INetworkDispatch { + + private NGECore core; + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + protected final Object objectMutex = new Object(); + + private boolean invasionScheduled = false; + + private CreatureObject invasionGeneral = null; + private CreatureObject defendingGeneral = null; + private CreatureObject defendingQuestOfficer = null; + private Vector offensiveQuestOfficers = new Vector(); + private boolean defendingGeneralAlive = true; + + private int invasionLocation=-1; + private String invasionPlanet="tatooine"; + + private Point3D invasionLocationCenter; + private int invadingFaction=Factions.Imperial; + private int defendingFaction=Factions.Rebel; + + private int invasionPhase=1; // Test phase 1 + + private Vector pylonList = new Vector(); + private Vector offensiveSupplyTerminals = new Vector(); + + private long temptimestartreference = 0L; + private boolean ph1_message1sent = false; + private boolean ph1_message2sent = false; + private boolean ph2_message1sent = false; + private boolean ph2_message2sent = false; + private boolean ph2_message3sent = false; + private boolean ph2_message4sent = false; + private boolean ph2_message5sent = false; + private boolean ph2_message6sent = false; + private boolean ph2_message7sent = false; + + private ScheduledFuture defendingGeneralTask = null; + private Map generalWarningLevelMap = new ConcurrentHashMap(); + + private Map invadingCreatures = new ConcurrentHashMap(); + private int invaderRegistryCounter = 0; + private Map defendingCreatures = new ConcurrentHashMap(); + private int defenderRegistryCounter = 0; + private Map demoralizedSoldiers = new ConcurrentHashMap(); + private int demoralizedSoldierRegistryCounter = 0; + private Map disabledVehicles = new ConcurrentHashMap(); + private int disabledVehicleRegistryCounter = 0; + private Map phase2Objects = new ConcurrentHashMap(); + private int phase2ObjectRegistryCounter = 0; + private Vector defensiveBanners = new Vector(); + private Vector defensiveSupplyTerminals = new Vector(); + private TangibleObject defensiveTable; + private Vector offensiveCamps = new Vector(); + + private List offensiveClonerList = new Vector(); + + public InvasionService(final NGECore core) { + this.core = core; + + Config options = core.getOptions(); + if (options != null && options.getInt("ENABLE.INVASIONS") == 0){ + return; + } + + + // Utility code +// Executors.newSingleThreadScheduledExecutor().schedule(() -> { +// arrangePylons(new Point3D(-1238.13F, 56, -3812.84F),100); +// }, 20, TimeUnit.SECONDS); + + + + // Local code to schedule a 20-30 minutes long phase2 invasion + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + + //testPylons(); + // temp time reference, will be server time later + while (NGECore.getInstance().getGalaxyStatus()!=GalaxyStatus.Online){ + try { + Thread.sleep(1000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + temptimestartreference = System.currentTimeMillis(); + scheduleInvasionManager(); + invasionScheduled=true; + scheduleInvasionEventManager(); + }, 60, TimeUnit.SECONDS); + // Local code to schedule a 20 minutes long phase2 invasion + + + // Server code to schedule invasions hourly + /* + for (;;){ + while (!invasionScheduled) { + Calendar now = Calendar.getInstance(); + // wait for the next full hour + if (now.get(Calendar.MINUTE)==0 && ! invasionScheduled){ + temptimestartreference = System.currentTimeMillis(); + scheduleInvasionManager(); + scheduleInvasionEventManager(); + invasionScheduled=true; + try { + if (!invasionScheduled) + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + try { + if (invasionScheduled) + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + */ + } + + public void scheduleInvasionManager(){ + + invasionLocation++; // Change Location of invasion + if (invasionLocation>2) + invasionLocation=0; // Rotate + + // Random for now + invasionLocation = new Random().nextInt(2); + + invasionPlanet = getInvasionPlanet(invasionLocation).getName(); + +// invasionLocation=InvasionLocation.Dearic; +// invasionPlanet="talus"; + +// invasionLocation=InvasionLocation.Keren; +// invasionPlanet="naboo"; + +// invasionLocation=InvasionLocation.Bestine; +// invasionPlanet="tatooine"; + + // Make sides random for now. + // Later GCWService will determine the sides + if (new Random().nextFloat()<0.5){ + invadingFaction=Factions.Rebel; + defendingFaction=Factions.Imperial; + } + + if (invasionLocation==InvasionLocation.Keren){ + spawnPylonsKeren(); + } + if (invasionLocation==InvasionLocation.Bestine){ + spawnPylonsBestine(); + } + if (invasionLocation==InvasionLocation.Dearic){ + spawnPylonsDearic(); + } + + spawnDefensiveAssets(); + spawnOffensiveAssets(); + + setInvasionLocationCenter(); + } + + public void scheduleInvasionEventManager(){ + + final Future[] evm = {null}; + evm[0] = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + if (!invasionScheduled){ + Thread.yield(); + evm[0].cancel(false); + } + invasionEventManager(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 10, 2000, TimeUnit.MILLISECONDS); + } + + public void invasionEventManager(){ + + // First message at 0:00 + if (invasionPhase==1 && System.currentTimeMillis()>temptimestartreference + 10 && ! ph1_message1sent){ + send_Phase1_InvaderMessage1(); + send_Phase1_DefenderMessage1(); + ph1_message1sent = true; + //System.out.println("Phase 1 msg1 sent "); + } + + // Message at 15:00 -> 900000 seconds + if (invasionPhase==1 && System.currentTimeMillis()>temptimestartreference + 50000 && ! ph1_message2sent){ + send_Phase1_InvaderMessage2(); + send_Phase1_DefenderMessage2(); + ph1_message2sent = true; + //System.out.println("Phase 1 msg2 sent "); + } + + // Message at 30:00 -> 1800000 seconds + if (invasionPhase==1 && System.currentTimeMillis()>temptimestartreference + 60000 && ! ph2_message1sent){ + invasionPhase=2; + preparePhase2(); + //System.out.println("PHASE 2"); + send_Phase2_InvaderMessage1(); + send_Phase2_DefenderMessage1(); + ph2_message1sent = true; + //System.out.println("Defender msg1 sent "); + } + + // Message at 45:00 -> 2700000 seconds + if (invasionPhase==2 && System.currentTimeMillis()>temptimestartreference + 900000 && ! ph2_message2sent){ // 1200000 + send_Phase2_InvaderMessage2(); + send_Phase2_DefenderMessage2(); + ph2_message2sent = true; + invasionPhase=3; + AIActor actor = (AIActor)defendingGeneral.getAttachment("AI"); + actor.setAIactive(true); + defendingGeneral.setOptionsBitmask(Options.ATTACKABLE); + + defendingGeneral.updatePvpStatus(); + + makeDefensiveGeneralDefenderForNPCs(); + //System.out.println("Defender msg2 sent "); // Local server gives only 30 mins time, so its ~15 mins for this phase + } + + if (defendingGeneral!=null){ + + if (invasionPhase==3 && defendingGeneral.getHealth()temptimestartreference + 1500000 && ! ph2_message3sent){ + sendDefenderWonMessage(); + sendInvaderLostMessage(); + ph2_message3sent = true; + invasionPhase=4; + + // Take care of GCW points + grantGCWPoints(invadingFaction,100); + grantGCWPoints(defendingFaction,1000); + + grantGCWTokens(invadingFaction,10); + grantGCWTokens(defendingFaction,130); + + playVictoryMusic(defendingFaction); + + // set up delayed tasks + //Clone Maps + Map invadingCreaturesClone = new ConcurrentHashMap(); + Map defendingCreaturesClone = new ConcurrentHashMap(); + for (Map.Entry entry : getInvadingCreaturesEntrySet()) { + invadingCreaturesClone.put(entry.getKey(), entry.getValue()); + } + for (Map.Entry entry : getDefendingCreaturesEntrySet()) { + defendingCreaturesClone.put(entry.getKey(), entry.getValue()); + } + + withdrawInvaders(); + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + wipeInvaders(invadingCreaturesClone); + wipeDefenders(defendingCreaturesClone); // Make sure all are deleted + }, 360, TimeUnit.SECONDS); + + + + for (BuildingObject camp : offensiveCamps){ + core.simulationService.remove(camp, camp.getWorldPosition().x, camp.getWorldPosition().z, true); + core.objectService.destroyObject(camp.getObjectID()); + } + + for (CreatureObject officer : offensiveQuestOfficers){ + core.simulationService.remove(officer, officer.getWorldPosition().x, officer.getWorldPosition().z, true); + core.objectService.destroyObject(officer.getObjectID()); + } + for (TangibleObject banner : defensiveBanners){ + core.objectService.destroyObject(banner.getObjectID()); + } + + if (defensiveTable!=null) + core.objectService.destroyObject(defensiveTable.getObjectID()); + if (defendingGeneral!=null) + core.objectService.destroyObject(defendingGeneral.getObjectID()); + if (defendingQuestOfficer!=null) + core.objectService.destroyObject(defendingQuestOfficer.getObjectID()); + if (invasionGeneral!=null) + core.objectService.destroyObject(invasionGeneral.getObjectID()); + + deletePhase2Objects(); + generalWarningLevelMap.clear(); + offensiveSupplyTerminals = new Vector(); + invaderRegistryCounter = 0; + defenderRegistryCounter = 0; + defensiveBanners.clear(); + defensiveSupplyTerminals.clear(); + defensiveTable = null; + defendingGeneralTask.cancel(true); + defendingGeneralTask = null; + + invasionScheduled = false; // free Service + } + + // General defeated + if (invasionPhase==3 && (defendingGeneral.getPosture()==13 || defendingGeneral.getPosture()==14) && ! ph2_message4sent){ + sendInvaderWonMessage(); + sendDefenderLostMessage(); + ph2_message4sent = true; + invasionPhase=4; // Post-Invasion phase + //System.out.println("Defender msg4 sent "); + + // Take care of GCW points + grantGCWPoints(invadingFaction,1000); + grantGCWPoints(defendingFaction,100); + + grantGCWTokens(invadingFaction,130); + grantGCWTokens(defendingFaction,10); + + playVictoryMusic(invadingFaction); + + // Clean Up +// wipeInvaders(); +// wipeDefenders(); + + // set up delayed tasks + //Clone Maps + Map invadingCreaturesClone = new ConcurrentHashMap(); + Map defendingCreaturesClone = new ConcurrentHashMap(); + for (Map.Entry entry : getInvadingCreaturesEntrySet()) { + invadingCreaturesClone.put(entry.getKey(), entry.getValue()); + } + for (Map.Entry entry : getDefendingCreaturesEntrySet()) { + defendingCreaturesClone.put(entry.getKey(), entry.getValue()); + } + + withdrawInvaders(); + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + wipeInvaders(invadingCreaturesClone); + wipeDefenders(defendingCreaturesClone); // Make sure all are deleted + }, 360, TimeUnit.SECONDS); + + + + for (BuildingObject camp : offensiveCamps){ + core.simulationService.remove(camp, camp.getWorldPosition().x, camp.getWorldPosition().z, true); + core.objectService.destroyObject(camp.getObjectID()); + } + + for (CreatureObject officer : offensiveQuestOfficers){ + core.simulationService.remove(officer, officer.getWorldPosition().x, officer.getWorldPosition().z, true); + core.objectService.destroyObject(officer.getObjectID()); + } + for (TangibleObject banner : defensiveBanners){ + core.objectService.destroyObject(banner.getObjectID()); + } + + if (defensiveTable!=null) + core.objectService.destroyObject(defensiveTable.getObjectID()); + if (defendingGeneral!=null) + core.objectService.destroyObject(defendingGeneral.getObjectID()); + if (defendingQuestOfficer!=null) + core.objectService.destroyObject(defendingQuestOfficer.getObjectID()); + if (invasionGeneral!=null) + core.objectService.destroyObject(invasionGeneral.getObjectID()); + + deletePhase2Objects(); + generalWarningLevelMap.clear(); + offensiveSupplyTerminals = new Vector(); + invaderRegistryCounter = 0; + defenderRegistryCounter = 0; + defensiveBanners.clear(); + defensiveSupplyTerminals.clear(); + defensiveTable = null; + defendingGeneralTask.cancel(true); + defendingGeneralTask = null; + + invasionScheduled = false; // free Service + } + + // General at half health + if (invasionPhase==3 && defendingGeneral.getHealth()<0.5*defendingGeneral.getMaxHealth() &&(defendingGeneral.getPosture()!=13 || defendingGeneral.getPosture()!=14) && ! ph2_message5sent){ + //sendInvaderGeneralHalfMessage(); + sendDefenderGeneralHalfMessage(); + ph2_message5sent = true; + } + } + } + + public void withdrawInvaders(){ + for (Map.Entry entry : getInvadingCreaturesEntrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + if (creature.getAttachment("AI")!=null){ + AIActor actor = (AIActor)creature.getAttachment("AI"); + if (actor!=null){ + actor.setActorAlive(true); + actor.setAIactive(true); + actor.setIntendedPrimaryAIState(new WithdrawalState()); + actor.setCurrentState(new WithdrawalState()); + creature.setAttachment("isWithdrawn",1); + } + } + } + } + } + + public void grantGCWPoints(int faction, int gcwPoints){ + String factionName = getFactionName(faction); + Vector allPlayers = core.simulationService.getAllNearSameFactionPlayers(500,invasionLocationCenter, getInvasionPlanet(invasionLocation), factionName); + for (CreatureObject player : allPlayers) { + if (player.getFaction().length() > 0 && player.getFactionStatus() > FactionStatus.OnLeave) { + core.gcwService.addGcwPoints(player, gcwPoints, GcwType.Enemy); + } + } + } + + public void grantGCWTokens(int faction, int tokenamount){ + String factionName = getFactionName(faction); + Vector allPlayers = core.simulationService.getAllNearSameFactionPlayers(500,invasionLocationCenter, getInvasionPlanet(invasionLocation), factionName); + for (CreatureObject player : allPlayers) { + if (player.getFaction().length() > 0 && player.getFactionStatus() > FactionStatus.OnLeave) { + + String tokenTemplate = "object/tangible/gcw/shared_gcw_rebel_token.iff"; + String name = "item_gcw_rebel_token"; + String description = "item_gcw_rebel_token"; + if (player.getFaction().equals(Factions.Imperial)){ + tokenTemplate = "object/tangible/gcw/shared_gcw_imperial_token.iff"; + name = "item_gcw_imperial_token"; + description = "item_gcw_imperial_token"; + } + TangibleObject token = (TangibleObject) core.objectService.createObject(tokenTemplate, player.getPlanet()); + + token.setStfFilename("static_item_n"); + token.setStfName(name); + token.setDetailFilename("static_item_d"); + token.setDetailName(description); + + token.setUses(tokenamount); + + player.sendSystemMessage("@static_item_n:"+name+" \\#32CD32 x" + tokenamount +" have been placed in your inventory \\#FFFFFF", (byte)0); + core.playerService.giveItem(player, token); + } + } + + } + + public void registerInvader(CreatureObject registrant){ + synchronized(invadingCreatures) { + // System.out.println("Registered! " + invaderRegistryCounter); + invadingCreatures.put(invaderRegistryCounter++, registrant); + } + } + + public void registerDefender(CreatureObject registrant){ + synchronized(defendingCreatures) { + defendingCreatures.put(defenderRegistryCounter++, registrant); + } + } + + public void registerDemoralizedSoldier(CreatureObject registrant){ + synchronized(demoralizedSoldiers) { + // System.out.println("Registered! " + invaderRegistryCounter); + demoralizedSoldiers.put(demoralizedSoldierRegistryCounter++, registrant); + } + } + + public void registerDisabledVehicle(CreatureObject registrant){ + synchronized(disabledVehicles) { + // System.out.println("Registered! " + invaderRegistryCounter); + disabledVehicles.put(disabledVehicleRegistryCounter++, registrant); + } + } + + public void wipeInvaders(Map invaderMap){ + + for (BuildingObject camp : offensiveCamps){ + core.simulationService.remove(camp, camp.getWorldPosition().x, camp.getWorldPosition().z, true); + core.objectService.destroyObject(camp.getObjectID()); + } + + for (CreatureObject officer : offensiveQuestOfficers){ + core.simulationService.remove(officer, officer.getWorldPosition().x, officer.getWorldPosition().z, true); + core.objectService.destroyObject(officer.getObjectID()); + } + + for (SWGObject cloner : offensiveClonerList){ + core.simulationService.remove(cloner, cloner.getWorldPosition().x, cloner.getWorldPosition().z, true); + core.objectService.destroyObject(cloner.getObjectID()); + } + + + for (Map.Entry entry : invaderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + if (creature.getAttachment("AI")!=null){ + AIActor actor = (AIActor)creature.getAttachment("AI"); + if (actor!=null){ + //System.out.println("Preparing deletion " + creature.getObjectID()); + actor.prepareDeletion(); + } + } + } + } + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + //System.out.println("Started schedule to destroy " + invaderMap.entrySet().size()); + for (Map.Entry entry : invaderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + if (creature.getAttachment("AI")!=null){ + AIActor actor = (AIActor)creature.getAttachment("AI"); + core.simulationService.remove(creature, creature.getWorldPosition().x, creature.getWorldPosition().z, true); // Make sure + //System.out.println("destroying Actor " + creature.getObjectID()); + actor.destroyActor(); + } + } + } + }, 5, TimeUnit.SECONDS); + + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + for (Map.Entry entry : invaderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + core.simulationService.remove(creature, creature.getWorldPosition().x, creature.getWorldPosition().z, true); // Make sure + core.objectService.destroyObject(creature.getObjectID()); + } + } + invaderMap.clear(); + //System.out.println("Destroyed all invaders."); + }, 15, TimeUnit.SECONDS); // Make sure remaining AI is finished with moves that might make them re-appear + } + + public void wipeDefenders(Map defenderMap){ + + for (TangibleObject banner : defensiveBanners){ + core.objectService.destroyObject(banner.getObjectID()); + } + + if (defensiveTable!=null) + core.objectService.destroyObject(defensiveTable.getObjectID()); + if (defendingGeneral!=null) + core.objectService.destroyObject(defendingGeneral.getObjectID()); + if (defendingQuestOfficer!=null) + core.objectService.destroyObject(defendingQuestOfficer.getObjectID()); + + for (Map.Entry entry : defenderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + if (creature.getAttachment("AI")!=null){ + AIActor actor = (AIActor)creature.getAttachment("AI"); + actor.prepareDeletion(); + } + } + } + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + for (Map.Entry entry : defenderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + if (creature.getAttachment("AI")!=null){ + AIActor actor = (AIActor)creature.getAttachment("AI"); + core.simulationService.remove(creature, creature.getWorldPosition().x, creature.getWorldPosition().z, true); // Make sure + actor.destroyActor(); + } + } + } + }, 5, TimeUnit.SECONDS); + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + for (Map.Entry entry : defenderMap.entrySet()) { + CreatureObject creature = entry.getValue(); + if (creature!=null){ + core.simulationService.remove(creature, creature.getWorldPosition().x, creature.getWorldPosition().z, true); // Make sure + core.objectService.destroyObject(creature.getObjectID()); + } + } + defenderMap.clear(); + //System.out.println("Destroyed all defenders."); + }, 15, TimeUnit.SECONDS); // Make sure remaining AI is finished with moves that might make them re-appear + + } + + + public void registerPhase2Objects(TangibleObject registrant){ + synchronized(phase2Objects){ + phase2Objects.put(phase2ObjectRegistryCounter++, registrant); + } + } + + public void deletePhase2Objects(){ + for (Map.Entry entry : phase2Objects.entrySet()) { + TangibleObject tano = entry.getValue(); + if (tano!=null){ + core.simulationService.remove(tano, tano.getWorldPosition().x, tano.getWorldPosition().z, true); // Make sure + core.objectService.destroyObject(tano.getObjectID()); + } + } + defendingCreatures.clear(); + } + + + public void spawnOffensiveAssets(){ + spawnOffensiveCamps(); + spawnOffensiveCloners(); + } + + public void spawnDefensiveAssets(){ + spawnDefendingGeneral(); + spawnDefensiveQuestOfficer(); + spawnBanners(); + spawnSupplyTerminals(); + spawnDefensivePlanningTable(); + } + + public void spawnDefensivePlanningTable(){ + if (invasionLocation==InvasionLocation.Keren){ + String template = "object/tangible/terminal/shared_planning_table_keren_reb.iff"; + if (defendingFaction==Factions.Imperial) + template = "object/tangible/terminal/shared_planning_table_keren_imp.iff"; + spawnDefensiveTable(new Point3D(1789.07F, 12, 2530.95F),new Quaternion(1,0F,0,0F),template); + } + if (invasionLocation==InvasionLocation.Bestine){ + String template = "object/tangible/terminal/shared_planning_table_bestine_reb.iff"; + if (defendingFaction==Factions.Imperial) + template = "object/tangible/terminal/shared_planning_table_bestine_imp.iff"; + spawnDefensiveTable(new Point3D(-1196.37F, 12, -3615.20F),new Quaternion(1,0F,0,0F),template); + } + if (invasionLocation==InvasionLocation.Dearic){ + String template = "object/tangible/terminal/shared_planning_table_dearic_reb.iff"; + if (defendingFaction==Factions.Imperial) + template = "object/tangible/terminal/shared_planning_table_dearic_imp.iff"; + spawnDefensiveTable(new Point3D(476.19F, 6, -3026.57F),new Quaternion(-0.37F,0F,0.92F,0F),template); + } + } + + public void spawnDefensiveTable(Point3D position, Quaternion quaternion, String template){ + + defensiveTable = (TangibleObject) core.objectService.createObject(template, 0, getInvasionPlanet(invasionLocation), position, quaternion); + core.simulationService.add(defensiveTable, defensiveTable.getPosition().x, defensiveTable.getPosition().z, true); + + String name = "gcw_reb_defense_table_n"; + String description = "gcw_reb_defense_table_d"; + if (defendingFaction==Factions.Imperial){ + name = "gcw_imp_defense_table_n"; + description = "gcw_imp_defense_table_d"; + } + + defensiveTable.setStfFilename("gcw"); + defensiveTable.setStfName(name); + defensiveTable.setDetailFilename("gcw"); + defensiveTable.setDetailName(description); + } + + public void spawnSupplyTerminals(){ + + if (invasionLocation==InvasionLocation.Keren){ + spawnDefensiveSupplyTerminal(new Point3D(1787.41F, 12, 2521.47F),new Quaternion(0,0F,1,0F)); + } + if (invasionLocation==InvasionLocation.Bestine){ + spawnDefensiveSupplyTerminal(new Point3D(-1212.58F, 12, -3614.57F),new Quaternion(0,0F,1,0F)); + } + if (invasionLocation==InvasionLocation.Dearic){ + spawnDefensiveSupplyTerminal(new Point3D(465.68F, 6, -3006.34F),new Quaternion(0,0F,1,0F)); + } + } + + public void spawnDefensiveSupplyTerminal(Point3D position, Quaternion quaternion){ + + // "object/tangible/terminal/shared_terminal_gcw_build_resource.iff" + String supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_reb_def.iff"; // shared_terminal_gcw_reb_def.iff + if (defendingFaction==Factions.Imperial) + supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_imp_def.iff"; + + TangibleObject supplyTerminal1 = (TangibleObject) core.objectService.createObject(supplyTerminalTemplate, 0, getInvasionPlanet(invasionLocation), position, quaternion); + core.simulationService.add(supplyTerminal1, supplyTerminal1.getPosition().x, supplyTerminal1.getPosition().z, true); + supplyTerminal1.setStfFilename("gcw"); + supplyTerminal1.setStfName("terminal_gcw_reb_def_n"); + supplyTerminal1.setDetailFilename("gcw"); + supplyTerminal1.setDetailName("terminal_gcw_reb_def_d"); + if (defendingFaction==Factions.Imperial){ + supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_imp_def.iff"; + supplyTerminal1.setStfFilename("gcw"); + supplyTerminal1.setStfName("terminal_gcw_reb_def_n"); + supplyTerminal1.setDetailFilename("gcw"); + supplyTerminal1.setDetailName("terminal_gcw_reb_def_d"); + } + defensiveSupplyTerminals.add(supplyTerminal1); + } + + public void supplyTerminalSUI(CreatureObject user, int childMenu){ + if (invasionPhase!=1) + return; // prevent exploit + String terminalName = "@gcw:terminal_gcw_reb_def_n"; + if (defendingFaction==Factions.Imperial) + terminalName = "@gcw:terminal_gcw_imp_def_n"; + + Map suiOptions = new HashMap(); + suiOptions.put((long) 1, "@gcw:gcw_barricade_tool_n"); + suiOptions.put((long) 2, "@gcw:gcw_spawner_tool_n"); + suiOptions.put((long) 3, "@gcw:gcw_turret_tool_n"); + suiOptions.put((long) 4, "@gcw:gcw_tower_tool_n"); + final SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, terminalName, "For now the tools are directly available.", suiOptions, user, null, 10); + Vector returnList = new Vector(); + + returnList.add("List.lstList:SelectedRow"); + window.addHandler(0, "", Trigger.TRIGGER_OK, returnList, new SUICallback() + { + public void process(SWGObject owner, int eventType, Vector returnList) + { + if (invasionPhase!=1) + return; // prevent exploit + int index = Integer.parseInt(returnList.get(0)); + int childIndex = (int) window.getObjectIdByIndex(index); + + CreatureObject player = (CreatureObject) owner; + SWGObject inventory = player.getSlottedObject("inventory"); + Planet planet = player.getPlanet(); + + switch(childIndex) + { + case 1: + TangibleObject barricadeTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_barricade_tool.iff", planet); + barricadeTool.setStfFilename("gcw"); + barricadeTool.setStfName("gcw_barricade_tool_n"); + barricadeTool.setDetailFilename("gcw"); + barricadeTool.setDetailName("gcw_barricade_tool_d"); + barricadeTool.setUses(10); + inventory.add(barricadeTool); + break; + + case 2: + TangibleObject spawnerTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_spawner_tool.iff", planet); + spawnerTool.setStfFilename("gcw"); + spawnerTool.setStfName("gcw_spawner_tool_n"); + spawnerTool.setDetailFilename("gcw"); + spawnerTool.setDetailName("gcw_spawner_tool_d"); + spawnerTool.setUses(10); + inventory.add(spawnerTool); + break; + + case 3: + TangibleObject turretTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_turret_tool.iff", planet); + turretTool.setStfFilename("gcw"); + turretTool.setStfName("gcw_turret_tool_n"); + turretTool.setDetailFilename("gcw"); + turretTool.setDetailName("gcw_turret_tool_d"); + turretTool.setUses(10); + inventory.add(turretTool); + break; + + case 4: + TangibleObject towerTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_tower_tool.iff", planet); + towerTool.setStfFilename("gcw"); + towerTool.setStfName("gcw_tower_tool_n"); + towerTool.setDetailFilename("gcw"); + towerTool.setDetailName("gcw_tower_tool_d"); + towerTool.setUses(10); + inventory.add(towerTool); + break; + } + } + }); + + core.suiService.openSUIWindow(window); + + } + + public void supplyOffensiveTerminalSUI(CreatureObject user, int childMenu){ + if (invasionPhase!=1) + return; // prevent exploit + String terminalName = "@gcw:terminal_gcw_reb_offensiv_n"; + if (defendingFaction==Factions.Imperial) + terminalName = "@gcw:terminal_gcw_imp_offensiv_n"; + Map suiOptions = new HashMap(); + suiOptions.put((long) 1, "@gcw:gcw_patrol_tool_n"); + suiOptions.put((long) 2, "@gcw:gcw_vehicle_tool_n"); + final SUIWindow window = core.suiService.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, terminalName, "For now the tools are directly available", suiOptions, user, null, 10); + Vector returnList = new Vector(); + + returnList.add("List.lstList:SelectedRow"); + window.addHandler(0, "", Trigger.TRIGGER_OK, returnList, new SUICallback() + { + public void process(SWGObject owner, int eventType, Vector returnList) + { + if (invasionPhase!=1) + return; // prevent exploit + int index = Integer.parseInt(returnList.get(0)); + int childIndex = (int) window.getObjectIdByIndex(index); + + CreatureObject player = (CreatureObject) owner; + SWGObject inventory = player.getSlottedObject("inventory"); + Planet planet = player.getPlanet(); + + switch(childIndex) + { + case 1: + TangibleObject barricadeTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_patrol_tool.iff", planet); + barricadeTool.setStfFilename("gcw"); + barricadeTool.setStfName("gcw_patrol_tool_n"); + barricadeTool.setDetailFilename("gcw"); + barricadeTool.setDetailName("gcw_patrol_tool_d"); + barricadeTool.setUses(10); + inventory.add(barricadeTool); + break; + + case 2: + TangibleObject spawnerTool = (TangibleObject) core.objectService.createObject("object/tangible/gcw/crafting_quest/shared_gcw_vehicle_tool.iff", planet); + spawnerTool.setStfFilename("gcw"); + spawnerTool.setStfName("gcw_vehicle_tool_n"); + spawnerTool.setDetailFilename("gcw"); + spawnerTool.setDetailName("gcw_vehicle_tool_d"); + spawnerTool.setUses(10); + inventory.add(spawnerTool); + break; + } + } + }); + + core.suiService.openSUIWindow(window); + } + + public void usePylon(CreatureObject user, GCWPylon pylon){ + + // check pylon filling status + if (pylon.getAttachment("Filling")==null) + return; + + if (user.getWorldPosition().getDistance2D(pylon.getWorldPosition())>7){ + user.sendSystemMessage("@gcw:pylon_too_far",(byte) 0); + return; + } + + int pylonFilling = (int) pylon.getAttachment("Filling"); + if (pylonFilling>=100){ + user.sendSystemMessage("@gcw:pylon_construction_complete",(byte) 0); + return; + } + + if (!(CRC.StringtoCRC(user.getFaction())==pylon.getPylonFaction())){ + user.sendSystemMessage("@gcw:pylon_construction_cannot_use",(byte) 0); + return; + } + + if (!user.getFaction().equals(getFactionName(pylon.getPylonFaction()))){ + return; + } + // ToDo: Consider Factional Helpers + if (user.getFaction().equals(getFactionName(pylon.getPylonFaction())) && user.getFactionStatus() tools = new Vector(); + user.getSlottedObject("inventory").viewChildren(user, true, false, new Traverser() { + @Override + public void process(SWGObject item) { + if (item.getTemplate().equals(foundToolTemplate)) { + if (tools.size()==0) + tools.add((TangibleObject)item); + else { + TangibleObject itemTANO = (TangibleObject)item; + if (itemTANO.getUses()[] fut = {null}; + fut[0] = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + //user.sendSystemMessage(""+countdown[0], (byte)0); + countdown[0]--; + // check if user has moved + if (userpos.getDistance2D(user.getWorldPosition())>0.2){ + // cancel count-down + fut[0].cancel(true); + cancelled[0] = true; + user.setConstructing(false); + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.sendSystemMessage("@gcw:pylon_construction_moved",(byte) 0); + } + if (user.isInCombat()){ + fut[0].cancel(true); + cancelled[0] = true; + user.setConstructing(false); + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.sendSystemMessage("@gcw:pylon_construction_entered_combat",(byte) 0); + } + if (user.getPosture()==13 & user.getPosture()==14){ + fut[0].cancel(true); + cancelled[0] = true; + user.setConstructing(false); + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.sendSystemMessage("@gcw:pylon_construction_incapacitated",(byte) 0); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 0, 1, TimeUnit.SECONDS); + + scheduler.schedule(new Runnable() { + @Override + public void run() { + try { + fut[0].cancel(true); + if (! cancelled[0]){ + TangibleObject tool = tools.get(0); + updatePylonFilling(pylon, tool); + user.setConstructing(false); + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + core.buffService.addBuffToCreature(user, "gcw_fatigue", user); + // increase fatigue + user.setGCWFatigue(user.getGCWFatigue()+1); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, constructiontimeagain, TimeUnit.SECONDS); + + } + + public void updatePylonFilling(GCWPylon pylon, TangibleObject tool){ + + int pylonFilling = (int)pylon.getAttachment("Filling"); + String pylonName = (String)pylon.getAttachment("Name"); + // determine power of tool + int power = 15; // assume 15 for now + + pylonFilling += power; + if (pylonFilling>100) + pylonFilling=100; + + String newPylonName = pylonName + " " + pylonFilling +"/100"; + pylon.setCustomName(newPylonName); + pylon.setAttachment("Filling",pylonFilling); + pylon.setResourceFilling(pylonFilling); + + + tool.setUses(tool.getUses()-1); + if (tool.getUses()==0){ + core.objectService.destroyObject(tool.getObjectID()); + } + } + + public void useBarricade(CreatureObject user, TangibleObject structure){ + + if (!user.getFaction().equals(getFactionName(defendingFaction))){ + return; + } + // ToDo: Consider Factional Helpers + if (user.getFaction().equals(getFactionName(defendingFaction)) && user.getFactionStatus()=structure.getMaximumCondition()){ + return; + } + if (user.isConstructing()) + return; + if (structureCondition<10000){ + user.sendSystemMessage("@gcw:gcw_object_doesnt_need_repair",(byte) 0); + return; + } + + + SUIWindow window = core.suiService.createSUIWindow("Script.countdownTimerBar", user, null, 5); + core.suiService.openTimerSUIWindow(window, "@gcw:reparing_gcw_object", 10); // also influenced by fatigue? + + user.setConstructing(true); + int repairtimeagain = 10; + int[] countdown = {repairtimeagain}; + final Point3D userpos = user.getWorldPosition(); + boolean[] cancelled = {false}; + final Future[] fut = {null}; + fut[0] = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + countdown[0]--; + // check if user has moved + if (userpos.getDistance2D(user.getWorldPosition())>0.2){ + // cancel count-down + fut[0].cancel(true); + cancelled[0] = true; + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.setConstructing(false); + user.sendSystemMessage("@gcw:pylon_construction_moved",(byte) 0); + } + if (user.isInCombat()){ + fut[0].cancel(true); + cancelled[0] = true; + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.setConstructing(false); + user.sendSystemMessage("@gcw:pylon_construction_entered_combat",(byte) 0); + } + if (user.getPosture()==13 & user.getPosture()==14){ + fut[0].cancel(true); + cancelled[0] = true; + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + user.setConstructing(false); + user.sendSystemMessage("@gcw:pylon_construction_incapacitated",(byte) 0); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 0, 1, TimeUnit.SECONDS); + + scheduler.schedule(new Runnable() { + @Override + public void run() { + try { + fut[0].cancel(true); + if (! cancelled[0]){ + int repairAmount = 5000; + int newCondition = structureCondition-repairAmount; + if (newCondition<0) + newCondition=0; + + structure.setConditionDamage(newCondition); + user.setConstructing(false); + tool.setUses(tool.getUses()-1); + if (tool.getUses()==0){ + core.objectService.destroyObject(tool.getObjectID()); + } + core.suiService.closeSUIWindow(window.getOwner(),window.getWindowId()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, repairtimeagain, TimeUnit.SECONDS); + + } + + public TangibleObject retrieveToolFromInventory(CreatureObject user, String toolTemplate){ + + if (toolTemplate.length()==0) + return null; + + // Find the according tool with the lowest uses in user's inventory + final String foundToolTemplate = toolTemplate; + Vector tools = new Vector(); + user.getSlottedObject("inventory").viewChildren(user, true, false, new Traverser() { + @Override + public void process(SWGObject item) { + if (item.getTemplate().equals(foundToolTemplate)) { + if (tools.size()==0) + tools.add((TangibleObject)item); + else { + TangibleObject itemTANO = (TangibleObject)item; + if (itemTANO.getUses()General is null"); + e.printStackTrace(); + } + } + defendingGeneralAlive = true; + + final Future[] dgt = {null}; + dgt[0] = defendingGeneralTask = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + AIActor actor = (AIActor)defendingGeneral.getAttachment("AI"); + if (actor.getCurrentState().getClass().equals(DeathState.class)){ + defendingGeneralAlive = false; + Thread.yield(); + dgt[0].cancel(false); + } + for (CreatureObject damager : actor.getDamageMap().keySet()){ + if (damager.getOwnerId()>0){ // For pets doing damage + damager = (CreatureObject)core.objectService.getObject(damager.getOwnerId()); + } + if (!damager.isPlayer()) + continue; + int warningLevel = 0; + + if (generalWarningLevelMap.get(damager)!=null) + warningLevel = generalWarningLevelMap.get(damager); + + if (actor.getDamageMap().get(damager)>3000 && warningLevel==0){ + // Warning 1 + generalWarningLevelMap.put(damager,1); + damager.sendSystemMessage("Attacking the general puts you at risk to become attackable by other players!", (byte) 0); + } + + if (actor.getDamageMap().get(damager)>10000 && warningLevel==1){ + // Warning 2 + generalWarningLevelMap.put(damager,2); + damager.sendSystemMessage("Continuing your attacks on the general will turn you special forces!", (byte) 0); + } + + if (actor.getDamageMap().get(damager)>15000 && warningLevel==2){ + // Warning 3 -> turn overt + generalWarningLevelMap.put(damager,3); + damager.sendSystemMessage("Your faction status is now special forces!", (byte) 0); + damager.setFactionStatus(FactionStatus.SpecialForces); + damager.updatePvpStatus(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 10, 5000, TimeUnit.MILLISECONDS); + + } + + public void spawnDefensiveQuestOfficer(){ + + String questOfficerTemplate = ""; + if (invadingFaction==Factions.Imperial){ + questOfficerTemplate = "rebel_defensive_quest_officer"; + } + if (invadingFaction==Factions.Rebel){ + questOfficerTemplate = "imp_defensive_quest_officer"; + } + + if (invasionLocation==InvasionLocation.Keren){ + defendingQuestOfficer = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "naboo", 0L, 1787, 12, 2531, 1, 0); + } + if (invasionLocation==InvasionLocation.Bestine){ + defendingQuestOfficer = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "tatooine", 0L, -1195, 12, -3620, 1, 0); + } + if (invasionLocation==InvasionLocation.Dearic){ + defendingQuestOfficer = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "talus", 0L, 478, 6, -3023, 0, 1); + } + } + + public void spawnOffensiveGeneral(){ + + String generalTemplate = "rebel_offensive_invasion_general"; + if (invadingFaction==Factions.Imperial){ + generalTemplate = "imp_offensive_invasion_general"; + } + + if (invasionLocation==InvasionLocation.Keren){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "naboo", 0L, 1206.99F, 7.33F, 3057.06F, 0.85F, 0.51F); + } + if (invasionLocation==InvasionLocation.Bestine){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "tatooine", 0L, -900, 12, -3782, 1, 0); + } + if (invasionLocation==InvasionLocation.Dearic){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "talus", 0L, -894.90F, 9.93F, -2993.29F, 0.96F, 0.26F); + } + + } + + public void spawnOffensiveCamps(){ + String campTemplate = "object/building/poi/shared_scout_camp_s5.iff"; + if (invadingFaction==Factions.Imperial){ + campTemplate = "object/building/poi/shared_scout_camp_s5.iff"; + } + if (invasionLocation==InvasionLocation.Keren){ + spawnOffensiveCamp(new Point3D(1820, 17, 2192),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(2131, 60, 2766),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(1212, 7, 3054),new Quaternion(1.00F,0F,0.00F,0F),campTemplate); + + spawnOffensiveQuestOfficer(new Point3D(1820, 17, 2192), new Quaternion(0.81F,0F,-0.58F,0F)); + spawnOffensiveQuestOfficer(new Point3D(2135.60F,60.0F,2769.78F), new Quaternion(-0.58F,0F,0.81F,0F)); + spawnOffensiveQuestOfficer(new Point3D(1212, 7, 3054), new Quaternion(0.51F,0F,0.85F,0F)); + + spawnOffensiveGeneral(); + + spawnOffensiveSupplyTerminal(new Point3D(1204.51F,7.33F,3054.27F), new Quaternion(0.28F,0F,0.95F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(2139.16F,60.0F,2765.92F), new Quaternion(0.98F,0F,-0.14F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(1828.02F,17.34F,2192.75F), new Quaternion(0.96F,0F,-0.26F,0F)); + } + if (invasionLocation==InvasionLocation.Bestine){ + spawnOffensiveCamp(new Point3D(-900,24, -3782),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(-1253,44.77F, -3348),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(-1184,62.95F, -3821),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + + spawnOffensiveQuestOfficer(new Point3D(-900,24, -3782), new Quaternion(0.81F,0F,-0.58F,0F)); + spawnOffensiveQuestOfficer(new Point3D(-1253,44, -3348), new Quaternion(-0.58F,0F,0.81F,0F)); + spawnOffensiveQuestOfficer(new Point3D(-1184,62, -3821), new Quaternion(0.51F,0F,0.85F,0F)); + + spawnOffensiveGeneral(); + + spawnOffensiveSupplyTerminal(new Point3D(-903,24, -3782), new Quaternion(0.28F,0F,0.95F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(-1256,44, -3348), new Quaternion(0.98F,0F,-0.14F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(-1188,62, -3821), new Quaternion(0.96F,0F,-0.26F,0F)); + } + if (invasionLocation==InvasionLocation.Dearic){ + + spawnOffensiveCamp(new Point3D(-890,9.93F, -2994),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(-2,6, -2805),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + spawnOffensiveCamp(new Point3D(352.85F,6F, -2606.14F),new Quaternion(0.00F,0F,1.00F,0F),campTemplate); + + spawnOffensiveGeneral(); + + spawnOffensiveQuestOfficer(new Point3D(-890,9, -2994), new Quaternion(0.81F,0F,-0.58F,0F)); + spawnOffensiveQuestOfficer(new Point3D(-1.70F,6, -2802.84F), new Quaternion(0.52F,0F,0.85F,0F)); + spawnOffensiveQuestOfficer(new Point3D(355,6, -2605), new Quaternion(0.00F,0F,1.00F,0F)); + + spawnOffensiveSupplyTerminal(new Point3D(-882.80F,9.93F, -2994.76F), new Quaternion(1.00F,0F,0.00F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(-1.33F,6, -2807.17F), new Quaternion(0.87F,0F,0.48F,0F)); + spawnOffensiveSupplyTerminal(new Point3D(347.56F,6, -2604.86F), new Quaternion(0.24F,0F,0.97F,0F)); + + } + } + + public void spawnOffensiveCamp(Point3D position, Quaternion quaternion, String campTemplate){ + // object/building/poi/shared_gcw_camp_rebel_recruiter.iff This IS the right template, but the client doesn't spawn it! + // This works at least object/building/poi/shared_scout_camp_s5.iff + BuildingObject camp = (BuildingObject) core.objectService.createObject(campTemplate, 0, getInvasionPlanet(invasionLocation), position, quaternion); + //TangibleObject camp = (TangibleObject) core.objectService.createObject(campTemplate, 0, core.terrainService.getPlanetByName("talus"), new Point3D(-890,9, -2994), quaternion); + core.simulationService.add(camp, camp.getPosition().x, camp.getPosition().z, true); + offensiveCamps.add(camp); + } + + + public void spawnOffensiveQuestOfficer(Point3D position, Quaternion quaternion){ + + String questOfficerTemplate = "rebel_invasion_captain"; + if (invadingFaction==Factions.Imperial) + questOfficerTemplate = "imp_invasion_captain"; + CreatureObject offensiveQuestOfficer = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(questOfficerTemplate, getInvasionPlanet(invasionLocation).getName(), 0L, position.x, position.y, position.z, quaternion.w, quaternion.x, quaternion.y,quaternion.z,-1); + offensiveQuestOfficers.add(offensiveQuestOfficer); + } + + public void spawnOffensiveSupplyTerminal(Point3D position, Quaternion quaternion){ + + // "object/tangible/terminal/shared_terminal_gcw_build_resource.iff" + String supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_reb_offensiv.iff"; + if (invadingFaction==Factions.Imperial) + supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_imp_offensiv.iff"; + + TangibleObject supplyTerminal1 = (TangibleObject) core.objectService.createObject(supplyTerminalTemplate, 0, getInvasionPlanet(invasionLocation), position, quaternion); + core.simulationService.add(supplyTerminal1, supplyTerminal1.getPosition().x, supplyTerminal1.getPosition().z, true); + supplyTerminal1.setStfFilename("gcw"); + supplyTerminal1.setStfName("terminal_gcw_reb_offensiv_n"); + supplyTerminal1.setDetailFilename("gcw"); + supplyTerminal1.setDetailName("terminal_gcw_reb_offensiv_d"); + if (invadingFaction==Factions.Imperial){ + supplyTerminalTemplate = "object/tangible/terminal/shared_terminal_gcw_imp_offensiv.iff"; + supplyTerminal1.setStfFilename("gcw"); + supplyTerminal1.setStfName("terminal_gcw_imp_offensiv_n"); + supplyTerminal1.setDetailFilename("gcw"); + supplyTerminal1.setDetailName("terminal_gcw_imp_offensiv_d"); + } + offensiveSupplyTerminals.add(supplyTerminal1); + } + + public void preparePhase2(){ + for (GCWPylon pylon : pylonList){ + pylon.convertToPhase2Object(); + core.objectService.destroyObject(pylon.getObjectID()); + } + pylonList.clear(); + pylonList = null; + for (TangibleObject defensiveSupplyTerminal : defensiveSupplyTerminals){ + core.objectService.destroyObject(defensiveSupplyTerminal.getObjectID()); + } + for (TangibleObject offensiveSupplyTerminal : offensiveSupplyTerminals){ + core.objectService.destroyObject(offensiveSupplyTerminal.getObjectID()); + } + + + } + + public void spawnBanners(){ + if (invasionLocation==InvasionLocation.Keren){ + spawnKerenBanners(); + } + if (invasionLocation==InvasionLocation.Bestine){ + spawnBestineBanners(); + } + if (invasionLocation==InvasionLocation.Dearic){ + spawnDearicBanners(); + } + } + + public void spawnDearicBanners(){ + + // Starport + createBanner(329.34F, 6, -2936.67F, 0.71F, 0.7F); + createBanner(329.34F, 6, -2925.15F, 0.71F, 0.7F); + + createBanner(414.98F, 6, -3027.86F, 0.71F, -0.7F); + createBanner(414.98F, 6, -2988.05F, 0.71F, -0.7F); + createBanner(448.98F, 6, -3028.05F, 0.68F, -0.73F); + createBanner(448.98F, 6, -2987.95F, 0.70F, 0.71F); + + createBanner(369.96F, 6, -2944.02F, 1.00F, 0.0F); + + createBanner(537.96F, 6, -3038.97F, 0.00F, 1.0F); + + createBanner(569.96F, 6, -2940.37F, 0.71F, -0.69F); + + createBanner(476.09F, 6, -2955.1F, 0.71F, 0.69F); + + createBanner(471.56F, 6, -3004.66F, 1.0F, 0.00F); + createBanner(488.40F, 6, -3004.66F, 1.0F, 0.00F); + + createBanner(524.88F, 6.51F, -3004.96F, 0.927F, 0.374F); + createBanner(525.03F, 6.51F, -2974.90F, 0.91F, -0.41F); + createBanner(555.13F, 6.51F, -2975.05F, 0.93F, 0.37F); + createBanner(555.15F, 6.51F, -3004.96F, 0.39F, 0.922F); + + } + + public void spawnKerenBanners(){ + + // Starport + createBanner(1436.87F, 13, 2764.41F, 0.71F, 0.7F); + createBanner(1436.46F, 13, 2777.70F, 0.71F, 0.7F); + + } + + public void spawnBestineBanners(){ + + // Starport + } + + public void createBanner(float x, float y, float z, float qy, float qw){ + Quaternion quaternion = new Quaternion(qy,0F,qw,0F); //object/installation/battlefield/destructible shared_banner_rebel_style_01.iff + String bannerTemplate = "object/tangible/gcw/shared_flip_banner_onpole_rebel.iff"; //object/tangible/event_perk/shared_banner_rebel_style_01.iff + String factionString = "rebel_banner"; + if (defendingFaction==Factions.Imperial){ + bannerTemplate = "object/tangible/gcw/shared_flip_banner_onpole_imperial.iff"; + factionString = "imperial_banner"; + } + TangibleObject banner = (TangibleObject) core.objectService.createObject(bannerTemplate, 0, getInvasionPlanet(invasionLocation), new Point3D(x, y, z), quaternion); + core.simulationService.add(banner, banner.getPosition().x, banner.getPosition().z, true); + banner.setStfFilename("obj_n"); + banner.setStfName(factionString); + banner.setDetailFilename("obj_d"); + banner.setDetailName(factionString); + defensiveBanners.add(banner); + } + + public int getInvasionPhase() { + return invasionPhase; + } + + public void setInvasionPhase(int invasionPhase) { + this.invasionPhase = invasionPhase; + } + + // Phase 1 messages + + public void send_Phase1_InvaderMessage1(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_call_to_arms_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_call_to_arms_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void send_Phase1_DefenderMessage1(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_construct_defenses_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_construct_defenses_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void send_Phase1_InvaderMessage2(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_rally_for_invasion_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_rally_for_invasion_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void send_Phase1_DefenderMessage2(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_building_almost_complete_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_building_almost_complete_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + + + // Phase 2 messages + + public void send_Phase2_InvaderMessage1(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_attack_city_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_attack_city_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void send_Phase2_DefenderMessage1(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_man_defenses_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_man_defenses_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void send_Phase2_InvaderMessage2(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_attack_half_done_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_attack_city_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void send_Phase2_DefenderMessage2(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_defense_half_done_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_defense_half_done_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void sendInvaderWonMessage(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_city_won_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_city_won_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void sendDefenderWonMessage(){ + String message = ""; + if (getInvasionLocationName().equals("talus_dearic")){ + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_won_attack_imeprial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_won_attack_rebel_" + getInvasionLocationName(); + } else { + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_city_safe_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_city_safe_rebel_" + getInvasionLocationName(); + } + sendMessageToClients(defendingFaction, message); + } + + public void sendInvaderLostMessage(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_city_lost_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_city_lost_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void sendCitySafeMessage(){ + String message = ""; + if (invadingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_city_end_safe_imperial_" + getInvasionLocationName(); + if (invadingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_city_end_safe_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void sendDefenderLostMessage(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_city_lost_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_city_lost_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void sendInvaderGeneralAttackMessage(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_attack_half_done_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_attack_half_done_rebel_" + getInvasionLocationName(); + sendMessageToClients(invadingFaction, message); + } + + public void sendDefenderGeneralAttackMessage(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_general_under_attack_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_general_under_attack_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void sendInvaderGeneralHalfMessage(){ // Is there any? +// String message = ""; +// if (defendingFaction==Factions.Imperial) +// message = "@gcw:gcw_announcement_city_lost_imperial_" + getInvasionLocationName(); +// if (defendingFaction==Factions.Rebel) +// message = "@gcw:gcw_announcement_city_lost_rebel_" + getInvasionLocationName(); +// sendMessageToClients(invadingFaction, message); + } + + public void sendDefenderGeneralHalfMessage(){ + String message = ""; + if (defendingFaction==Factions.Imperial) + message = "@gcw:gcw_announcement_invasion_almost_defeated_imperial_" + getInvasionLocationName(); + if (defendingFaction==Factions.Rebel) + message = "@gcw:gcw_announcement_invasion_almost_defeated_rebel_" + getInvasionLocationName(); + sendMessageToClients(defendingFaction, message); + } + + public void sendMessageToClients(int tofaction, String message){ + String modelTemplate = defendingGeneral.getTemplate(); + if (invadingFaction==tofaction) + modelTemplate = invasionGeneral.getTemplate(); + + ConcurrentHashMap clients = NGECore.getInstance().getActiveConnectionsMap(); + for (Map.Entry entry : clients.entrySet()) { + Client client = entry.getValue(); + if (client.getParent()!=null){ + String faction = ((CreatureObject)client.getParent()).getFaction(); + if (client.getParent().getPlanet().equals(getInvasionPlanet(invasionLocation)) && faction.equals(getFactionName(tofaction))){ + CommPlayerMessage comm = new CommPlayerMessage(client.getParent().getObjectId(), OutOfBand.ProsePackage(message)); + comm.setTime(2000); + comm.setModel(modelTemplate); + client.getSession().write(comm.serialize()); + } + } + } + } + + + + public Planet getInvasionPlanet(int location){ + Planet planet = null; + switch (location){ + case InvasionLocation.Dearic : planet = core.terrainService.getPlanetByName("talus"); + break; + case InvasionLocation.Keren : planet = core.terrainService.getPlanetByName("naboo"); + break; + case InvasionLocation.Bestine : planet = core.terrainService.getPlanetByName("tatooine"); + break; + } + return planet; + } + + public void makeDefensiveGeneralDefenderForNPCs(){ + Vector enemies = core.simulationService.getAllNearNonSameFactionNPCs(50, defendingGeneral); + if (defendingGeneral==null) + return; + for (CreatureObject enemy : enemies) { + AIActor actor = (AIActor)enemy.getAttachment("AI"); + if (actor==null) + return; + actor.setLastPositionBeforeStateChange(enemy.getWorldPosition()); + actor.addDefender(defendingGeneral); + } + } + + public float getDistanceToDefensiveGeneral(CreatureObject checker){ + //float dist = checker.getWorldPosition().getDistance2D(defendingGeneral.getWorldPosition()); + //return dist; + return NGECore.getInstance().aiService.distanceSquared2D(defendingGeneral.getWorldPosition(), checker.getWorldPosition()); + } + + public CreatureObject getDefensiveGeneral(){ + return defendingGeneral; + } + + public boolean checkInvasionDeath(CreatureObject dead){ + boolean value = false; + if (invasionScheduled){ + String funeralSite = dead.getPlanet().getName(); + if (funeralSite.equals(invasionPlanet)){ + if (invasionLocationCenter.getDistance2D(dead.getWorldPosition())<500){ + value = true; + } + } + } + return value; + } + + public List getAccordingCloners(CreatureObject dead){ + List clonerList = new Vector(); + if (invasionScheduled){ + String funeralSite = dead.getPlanet().getName(); + if (funeralSite.equals(invasionPlanet)){ + if (invasionLocationCenter.getDistance2D(dead.getWorldPosition())<500){ + if (isInvadingFaction(dead)){ + clonerList = getInvaderClonersForPlanet(); + } + } + } + } + return clonerList; + } + + public List getInvaderClonersForPlanet(){ + return offensiveClonerList; + } + + public boolean isInvadingFaction(CreatureObject checker){ + if (checker.getFaction().equals(getFactionName(invadingFaction))) + return true; + return false; + } + + public boolean isdefendingFaction(CreatureObject checker){ + if (checker.getFaction().equals(getFactionName(defendingFaction))) + return true; + return false; + } + + private void spawnOffensiveCloners(){ + String clonerTemplate = "object/tangible/gcw/static_base/shared_invisible_cloner_rebel.iff"; + if (invadingFaction==Factions.Imperial){ + clonerTemplate = "object/tangible/gcw/static_base/shared_invisible_cloner_imperial.iff"; + } + + Point3D cloner1Pos = null; + Point3D cloner2Pos = null; + Point3D cloner3Pos = null; + switch (invasionPlanet) { + case "naboo": cloner1Pos = new Point3D(1814.81F, 17.34F, 2183.17F); + cloner2Pos = new Point3D(2125.71F, 60, 2756.94F); + cloner3Pos = new Point3D(1217.18F, 7.33F, 3062.95F); + break; + case "tatooine": cloner1Pos = new Point3D(-905.35F,24, -3791.04F); + cloner2Pos = new Point3D(-1258.13F,44.77F, -3357.66F); + cloner3Pos = new Point3D(-1189.65F,62.95F, -3830.22F); + break; + case "talus": cloner1Pos = new Point3D(-895.30F,9.93F, -3003.25F); + cloner2Pos = new Point3D(-7.27F,6, -2813.55F); + cloner3Pos = new Point3D(347.51F,6F, -2614.82F); + break; + } + + BuildingObject cloner1 = (BuildingObject) NGECore.getInstance().objectService.createObject(clonerTemplate, 0, core.terrainService.getPlanetByName(invasionPlanet), cloner1Pos, new Quaternion(0.00F,0F,1.00F,0F)); + NGECore.getInstance().simulationService.add(cloner1, cloner1.getPosition().x, cloner1.getPosition().z, true); + cloner1.setCustomName("Attack camp #1"); + Vector spawnPoints = new Vector(); + spawnPoints.add(new SpawnPoint(cloner1Pos,0F,1F)); + cloner1.setAttachment("spawnPoints", spawnPoints); + core.mapService.addLocation(cloner1.getPlanet(), "Attack camp #1", cloner1.getPosition().x, cloner1.getPosition().z, (byte)5, (byte)0, (byte)0); + + BuildingObject cloner2 = (BuildingObject) NGECore.getInstance().objectService.createObject(clonerTemplate, 0, core.terrainService.getPlanetByName(invasionPlanet), cloner2Pos, new Quaternion(0.00F,0F,1.00F,0F)); + NGECore.getInstance().simulationService.add(cloner2, cloner2.getPosition().x, cloner2.getPosition().z, true); + cloner2.setCustomName("Attack camp #2"); + spawnPoints = new Vector(); + spawnPoints.add(new SpawnPoint(cloner2Pos,0F,1F)); + cloner2.setAttachment("spawnPoints", spawnPoints); + core.mapService.addLocation(cloner2.getPlanet(), "Attack camp #2", cloner2.getPosition().x, cloner2.getPosition().z, (byte)5, (byte)0, (byte)0); + + BuildingObject cloner3 = (BuildingObject) NGECore.getInstance().objectService.createObject(clonerTemplate, 0, core.terrainService.getPlanetByName(invasionPlanet), cloner3Pos, new Quaternion(0.00F,0F,1.00F,0F)); + NGECore.getInstance().simulationService.add(cloner3, cloner3.getPosition().x, cloner3.getPosition().z, true); + cloner3.setCustomName("Attack camp #3"); + spawnPoints = new Vector(); + spawnPoints.add(new SpawnPoint(cloner3Pos,0F,1F)); + cloner3.setAttachment("spawnPoints", spawnPoints); + core.mapService.addLocation(cloner3.getPlanet(), "Attack camp #3", cloner3.getPosition().x, cloner3.getPosition().z, (byte)5, (byte)0, (byte)0); + + offensiveClonerList.add(cloner1); + offensiveClonerList.add(cloner2); + offensiveClonerList.add(cloner3); + } + + private void spawnDemoralizedSoldier(int faction, Point3D pos, float qw, float qy){ + String soldierTemplate = "rebel_invasion_demoralized_soldier"; + if (faction==Factions.Imperial){ + soldierTemplate = "imp_invasion_demoralized_soldier"; + } + + CreatureObject soldier = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(soldierTemplate, getInvasionPlanet(invasionLocation).getName(), 0L, pos.x, pos.y, pos.z, qw,0F,qy,0F,-1); + NGECore.getInstance().invasionService.registerDemoralizedSoldier(soldier); + } + + private void spawnDisabledVehicle(int faction, Point3D pos, float qw, float qy){ + String vehicleTemplate = "rebel_invasion_disabled_atxt"; + if (faction==Factions.Imperial){ + vehicleTemplate = "imp_invasion_disabled_atst"; + } + + CreatureObject vehicle = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(vehicleTemplate, getInvasionPlanet(invasionLocation).getName(), 0L, pos.x, pos.y, pos.z, qw,0F,qy,0F,-1); + vehicle.setPosture((byte) Posture.Incapacitated); + NGECore.getInstance().invasionService.registerDisabledVehicle(vehicle); + } + + private void playVictoryMusic(int winnerFaction){ + String audioTemplate = "sound/music_themequest_victory_rebel.snd"; + if (winnerFaction==Factions.Imperial) + audioTemplate = "sound/music_themequest_victory_imperial.snd"; + +// Vector allPlayers = core.simulationService.getAllNearSameFactionPlayers(500,invasionLocationCenter, getInvasionPlanet(invasionLocation), getFactionName(winnerFaction)); +// for (CreatureObject player : allPlayers) { +// if (player.getFaction().length() > 0 && player.getFactionStatus() > FactionStatus.OnLeave) { +// player.playMusic(audioTemplate); +// } +// } + Vector allPlayers = core.simulationService.getAllNearPlayers(500, getInvasionPlanet(invasionLocation), invasionLocationCenter); + for (CreatureObject player : allPlayers) { + player.playMusic(audioTemplate); + } + } + + // Utility method + public void arrangePylons(Point3D center, int angle){ + + int pylondistance= 4; + + Point3D pylonRefPos1 = new Point3D(-2*pylondistance,0,-pylondistance); + Point3D pylonRefPos2 = new Point3D(-pylondistance,0,pylondistance); + Point3D pylonRefPos3 = new Point3D(0,0,-pylondistance); + Point3D pylonRefPos4 = new Point3D(pylondistance,0,pylondistance); + Point3D pylonRefPos5 = new Point3D(2*pylondistance,0,-pylondistance); + + Point3D pylonTurnedPos1 = turnPoint(pylonRefPos1, angle); + Point3D pylonTurnedPos2 = turnPoint(pylonRefPos2, angle); + Point3D pylonTurnedPos3 = turnPoint(pylonRefPos3, angle); + Point3D pylonTurnedPos4 = turnPoint(pylonRefPos4, angle); + Point3D pylonTurnedPos5 = turnPoint(pylonRefPos5, angle); + + + float positionY1 = core.terrainService.getHeight(getInvasionPlanet(invasionLocation).getID(), center.x + pylonTurnedPos1.x, center.z + pylonTurnedPos1.z); + float positionY2 = core.terrainService.getHeight(getInvasionPlanet(invasionLocation).getID(), center.x + pylonTurnedPos2.x, center.z + pylonTurnedPos2.z); + float positionY3 = core.terrainService.getHeight(getInvasionPlanet(invasionLocation).getID(), center.x + pylonTurnedPos3.x, center.z + pylonTurnedPos3.z); + float positionY4 = core.terrainService.getHeight(getInvasionPlanet(invasionLocation).getID(), center.x + pylonTurnedPos4.x, center.z + pylonTurnedPos4.z); + float positionY5 = core.terrainService.getHeight(getInvasionPlanet(invasionLocation).getID(), center.x + pylonTurnedPos5.x, center.z + pylonTurnedPos5.z); + + Point3D pylonWorldPos1 = new Point3D(center.x + pylonTurnedPos1.x,positionY1,center.z + pylonTurnedPos1.z); + Point3D pylonWorldPos2 = new Point3D(center.x + pylonTurnedPos2.x,positionY2,center.z + pylonTurnedPos2.z); + Point3D pylonWorldPos3 = new Point3D(center.x + pylonTurnedPos3.x,positionY3,center.z + pylonTurnedPos3.z); + Point3D pylonWorldPos4 = new Point3D(center.x + pylonTurnedPos4.x,positionY4,center.z + pylonTurnedPos4.z); + Point3D pylonWorldPos5 = new Point3D(center.x + pylonTurnedPos5.x,positionY5,center.z + pylonTurnedPos5.z); + + System.out.println("new Point3D(" + pylonWorldPos1.x + "F, " + pylonWorldPos1.y + "F, " + pylonWorldPos1.z + "F)"); + System.out.println("new Point3D(" + pylonWorldPos2.x + "F, " + pylonWorldPos2.y + "F, " + pylonWorldPos2.z + "F)"); + System.out.println("new Point3D(" + pylonWorldPos3.x + "F, " + pylonWorldPos3.y + "F, " + pylonWorldPos3.z + "F)"); + System.out.println("new Point3D(" + pylonWorldPos4.x + "F, " + pylonWorldPos4.y + "F, " + pylonWorldPos4.z + "F)"); + System.out.println("new Point3D(" + pylonWorldPos5.x + "F, " + pylonWorldPos5.y + "F, " + pylonWorldPos5.z + "F)"); + } + + private Point3D turnPoint(Point3D orig, int angle){ + double origangle = Math.toDegrees(Math.atan2(orig.x, orig.z)); + double hypo = Math.sqrt(orig.x*orig.x+orig.z*orig.z); + double newAngle = origangle + angle; + float newX = (float)(hypo * Math.sin(Math.toRadians(newAngle))); + float newZ = (float)(hypo * Math.cos(Math.toRadians(newAngle))); + Point3D result = new Point3D(newX,0,newZ); + return result; + } + + private Set> getInvadingCreaturesEntrySet(){ + synchronized(invadingCreatures){ + return invadingCreatures.entrySet(); + } + } + + private Set> getDefendingCreaturesEntrySet(){ + synchronized(defendingCreatures){ + return defendingCreatures.entrySet(); + } + } + + + public void setInvasionLocationCenter(){ + switch (invasionLocation){ + case InvasionLocation.Dearic : invasionLocationCenter = new Point3D(452,6,-3002); + break; + case InvasionLocation.Keren : invasionLocationCenter = new Point3D(1840,12,2635); + break; + case InvasionLocation.Bestine : invasionLocationCenter = new Point3D(-1192,12,-3606); + break; + } + } + + public String getInvasionLocationName(){ + switch (invasionLocation){ + case InvasionLocation.Dearic : return "talus_dearic"; + case InvasionLocation.Keren : return "naboo_keren"; + case InvasionLocation.Bestine : return "tatooine_bestine"; + } + return ""; + } + + public String getFactionName(int faction){ + if (faction==Factions.Rebel) + return "rebel"; + if (faction==Factions.Imperial) + return "imperial"; + return "neutral"; + } + + + public boolean isDefendingGeneralAlive() { + return defendingGeneralAlive; + } + + @Override + public void shutdown() { + + } + @Override + public void insertOpcodes(Map arg0, + Map arg1) { + } + + public class InvasionLocation { + + public static final int Keren = 0; + public static final int Bestine = 1; + public static final int Dearic = 2; + + } + + public int getInvasionLocation() { + return invasionLocation; + } + + public String getInvasionPlanetName() { + return getInvasionPlanet(invasionLocation).getName(); + } + + public void setInvasionLocation(int invasionLocation) { + this.invasionLocation = invasionLocation; + } +} diff --git a/src/services/gcw/VehiclePatrolPylon.java b/src/services/gcw/VehiclePatrolPylon.java new file mode 100644 index 00000000..68bd68a1 --- /dev/null +++ b/src/services/gcw/VehiclePatrolPylon.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.gcw; + +import java.util.Random; +import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import main.NGECore; +import resources.datatables.Factions; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; + +/** + * @author Charon + */ + +@SuppressWarnings("unused") +public class VehiclePatrolPylon extends TangibleObject{ + + private static final long serialVersionUID = 1L; + private int pylonFaction = 0; + private int spawnLevel = 0; + private int totalSpawnedVehicles = 0; + private String[] vehicleTemplates = new String[]{""}; + private String[] rebelTemplates1 = new String[]{""}; + private String[] rebelTemplates2 = new String[]{""}; + private String[] rebelTemplates3 = new String[]{""}; + private String[] imperialTemplates1 = new String[]{""}; + private String[] imperialTemplates2 = new String[]{""}; + private String[] imperialTemplates3 = new String[]{"elite_imperial_stormtrooper_90"}; + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public VehiclePatrolPylon() { + super(); + } + + public VehiclePatrolPylon(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ + super(objectID, planet, position, orientation, template); + + scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + spawnVehicle(); + } catch (Exception e) { + System.err.println("Exception in VehiclePatrolPylon->scheduleAtFixedRate->spawnVehicle() " + e.getMessage()); + } + } + }, 5, 20, TimeUnit.SECONDS); + + } + + public int getPylonFaction() { + return pylonFaction; + } + + public void setPylonFaction(int pylonFaction) { + this.pylonFaction = pylonFaction; + } + + public int getSpawnLevel() { + return spawnLevel; + } + + public void setSpawnLevel(int spawnLevel) { + this.spawnLevel = spawnLevel; + } + + public void spawnVehicle(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + if (pylonFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: vehicleTemplates = rebelTemplates1; + case 2: vehicleTemplates = rebelTemplates2; + case 3: vehicleTemplates = rebelTemplates3; + } + } + if (pylonFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: vehicleTemplates = imperialTemplates1; + case 2: vehicleTemplates = imperialTemplates2; + case 3: vehicleTemplates = imperialTemplates3; + } + } + String vehicleTemplate = vehicleTemplates[new Random().nextInt(vehicleTemplates.length)]; + CreatureObject vehicle = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(vehicleTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + + NGECore.getInstance().aiService.setPatrol(vehicle, get_Dearic_Route_1()); + NGECore.getInstance().aiService.setPatrolLoop(vehicle,false); + totalSpawnedVehicles++; + } + } + + public Vector get_Dearic_Route_1(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(68.0F, 6.00F, -2959F)); + patrolpoints.add(new Point3D(151.93F,6.00F, -2961.66F)); + patrolpoints.add(new Point3D(170.18F, 6.00F, -2992.99F)); + patrolpoints.add(new Point3D(262.76F, 6.00F, -2999.76F)); + patrolpoints.add(new Point3D(275.87F, 6.00F, -3008.44F)); + patrolpoints.add(new Point3D(303.41F, 6.00F, -3005.19F)); + patrolpoints.add(new Point3D(343.31F, 6.00F, -2961.06F)); + patrolpoints.add(new Point3D(379.98F, 6.00F, -2963.31F)); + patrolpoints.add(new Point3D(404.70F, 6.00F, -2980.57F)); + patrolpoints.add(new Point3D(412.54F, 6.00F, -3039.39F)); + patrolpoints.add(new Point3D(423.06F, 6.00F, -3050.75F)); + patrolpoints.add(new Point3D(446.92F, 6.00F, -3046.32F)); + patrolpoints.add(new Point3D(470.48F, 6.00F, -3023.43F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_2(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_3(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_4(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_5(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_6(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_7(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_8(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + public Vector get_Dearic_Route_9(){ + Vector patrolpoints = new Vector(); + return patrolpoints; + } + + + +} diff --git a/src/services/housing/HousingService.java b/src/services/housing/HousingService.java index 3d897d43..89fbf577 100644 --- a/src/services/housing/HousingService.java +++ b/src/services/housing/HousingService.java @@ -92,7 +92,7 @@ public class HousingService implements INetworkDispatch { public void enterStructureMode(CreatureObject actor, TangibleObject deed) { PlayerCity city = core.playerCityService.getCityObjectIsIn(actor); - if (!actor.getClient().isGM() && !core.terrainService.canBuildAtPosition(actor, actor.getWorldPosition().x, actor.getWorldPosition().z)) { + if (core.adminService.getAccessLevelFromDB(actor.getClient().getAccountId()) == null && !core.terrainService.canBuildAtPosition(actor, actor.getWorldPosition().x, actor.getWorldPosition().z)) { actor.sendSystemMessage("You may not place a structure here.", (byte) 0); // should probably load this from an stf return; } @@ -122,7 +122,7 @@ public class HousingService implements INetworkDispatch { return null; } - if(!actor.getClient().isGM() && !core.terrainService.canBuildAtPosition(actor, positionX, positionZ)) { + if(core.adminService.getAccessLevelFromDB(actor.getClient().getAccountId()) == (null) && !core.terrainService.canBuildAtPosition(actor, positionX, positionZ)) { actor.sendSystemMessage("You may not place a structure here.", (byte) 0); // should probably load this from an stf return null; } diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 7ede2796..9bd27972 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -132,6 +132,9 @@ import services.command.CombatCommand; import services.bazaar.AuctionItem; import services.chat.ChatRoom; import services.equipment.EquipmentService; +import services.gcw.GCWPylon; +import services.gcw.GCWSpawner; +import services.spawn.MobileTemplate; import services.sui.SUIWindow; import services.sui.SUIWindow.SUICallback; import services.sui.SUIWindow.Trigger; @@ -303,6 +306,39 @@ public class ObjectService implements INetworkDispatch { object = new SurveyTool(objectID, planet, position, orientation, Template); + } else if(Template.startsWith("object/tangible/destructible/shared_gcw_city_construction_beacon")) { + + float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1.5f; + Point3D newpoint = new Point3D(position.x,positionY,position.z); + object = new GCWPylon(objectID, planet, position, orientation, Template); + + } else if(Template.startsWith("object/tangible/loot/creature_loot/collections/shared_dejarik_table_base")) { + + float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)+0.3f; + Point3D newpoint = new Point3D(position.x,positionY,position.z); + object = new GCWSpawner(objectID, planet, position, orientation, Template); + + } else if(Template.startsWith("object/tangible/destructible/")) { + +// float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1f; +// Point3D newpoint = new Point3D(position.x,positionY,position.z); +// object = new InstallationObject(objectID, planet, newpoint, orientation, Template); + + object = new TangibleObject(objectID, planet, position, orientation, Template); + + //object = new BuildingObject(objectID, planet, position, orientation, Template); + + } else if(Template.startsWith("object/tangible/gcw/static_base/shared_invisible_cloner")) { + + object = new BuildingObject(objectID, planet, position, orientation, Template); + if(!isSnapshot && !overrideSnapshot && object.getPortalVisitor() != null) { + int cellCount = object.getPortalVisitor().cells.size() - 1; // -1 for index 0 cell which is outside the building and used for ai pathfinding + for (int i = 0; i < cellCount; i++) { + CellObject cell = (CellObject) createObject("object/cell/shared_cell.iff", planet); + cell.setCellNumber(i+1); + object.add(cell); + } + } } else if(Template.startsWith("object/tangible")) { object = new TangibleObject(objectID, planet, position, orientation, Template); @@ -393,6 +429,12 @@ public class ObjectService implements INetworkDispatch { Point3D newpoint = new Point3D(position.x,positionY,position.z); object = new HarvesterObject(objectID, planet, newpoint, orientation, Template); + } else if(Template.startsWith("object/installation/turret")) { + + float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z); + Point3D newpoint = new Point3D(position.x,positionY,position.z); + object = new InstallationObject(objectID, planet, newpoint, orientation, Template); + } else { return null; } @@ -549,19 +591,25 @@ public class ObjectService implements INetworkDispatch { if (object.getAttachment("AI") != null && object.getAttachment("AI") instanceof AIActor && ((AIActor) object.getAttachment("AI")).getMobileTemplate().getRespawnTime() > 0) { final long objectId = object.getObjectID(); - final String Template = object.getTemplate(); + final MobileTemplate Template = ((AIActor) object.getAttachment("AI")).getMobileTemplate(); final Planet planet = object.getPlanet(); final Point3D position = object.getPosition(); + final Point3D spawnPosition = ((AIActor) object.getAttachment("AI")).getSpawnPosition(); final Quaternion orientation = object.getOrientation(); - final long cellId = ((object.getContainer() == null) ? 0L : object.getContainer().getObjectID()); + // final long cellId = ((object.getContainer() == null) ? 0L : object.getContainer().getObjectID()); + CellObject cellO = spawnPosition.getCell(); + final long cellId = ((cellO == null) ? 0L : cellO.getObjectID()); final short level = ((object instanceof CreatureObject) ? ((CreatureObject) object).getLevel() : (short) 0); - scheduler.schedule(new Runnable() { @Override public void run() { try { - NGECore.getInstance().spawnService.spawnCreature(Template, objectId, planet.getName(), cellId, position.x, position.y, position.z, orientation.w, orientation.x, orientation.y, orientation.z, level); + // Commented for now until found where the respawn is always set to 60 for any NPC +// CreatureObject newObject = NGECore.getInstance().spawnService.spawnCreature(Template, 0, planet.getName(), cellId, spawnPosition.x, spawnPosition.y, spawnPosition.z, orientation.w, orientation.x, orientation.y, orientation.z, level); +// AIActor newAIActor = (AIActor)newObject.getAttachment("AI"); +// newAIActor.cloneActor(((AIActor) object.getAttachment("AI"))); + //object.setAttachment("AI", null); } catch (Exception e) { e.printStackTrace(); } @@ -569,7 +617,7 @@ public class ObjectService implements INetworkDispatch { }, ((AIActor) object.getAttachment("AI")).getMobileTemplate().getRespawnTime(), TimeUnit.SECONDS); } - + String filePath = "scripts/" + object.getTemplate().split("shared_" , 2)[0].replace("shared_", "") + object.getTemplate().split("shared_" , 2)[1].replace(".iff", "") + ".py"; if (FileUtilities.doesFileExist(filePath)) { @@ -1279,7 +1327,6 @@ public class ObjectService implements INetworkDispatch { } public void loadBuildoutObjects(Planet planet) throws InstantiationException, IllegalAccessException { - DatatableVisitor buildoutTable = ClientFileManager.loadFile("datatables/buildout/areas_" + planet.getName() + ".iff", DatatableVisitor.class); for (int i = 0; i < buildoutTable.getRowCount(); i++) { @@ -1287,7 +1334,6 @@ public class ObjectService implements INetworkDispatch { String areaName = (String) buildoutTable.getObject(i, 0); float x1 = (Float) buildoutTable.getObject(i, 1); float z1 = (Float) buildoutTable.getObject(i, 2); - readBuildoutDatatable(ClientFileManager.loadFile("datatables/buildout/" + planet.getName() + "/" + areaName + ".iff", DatatableVisitor.class), planet, x1, z1); } diff --git a/src/services/resources/HarvesterService.java b/src/services/resources/HarvesterService.java index 96b68aad..7b729f64 100644 --- a/src/services/resources/HarvesterService.java +++ b/src/services/resources/HarvesterService.java @@ -1063,7 +1063,7 @@ public class HarvesterService implements INetworkDispatch { WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", actor.getPlanet(), harvester.getPosition().x, 0 ,harvester.getPosition().z); String displayname = "@installation_n:"+harvester.getStfName(); constructionWaypoint.setName(displayname); - constructionWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(actor.getPlanet().getName())); + constructionWaypoint.setPlanetCrc(CRC.StringtoCRC(actor.getPlanet().getName())); constructionWaypoint.setPosition(new Point3D(object.getPosition().x,0, object.getPosition().z)); player.waypointAdd(constructionWaypoint); constructionWaypoint.setPosition(new Point3D(object.getPosition().x,0, object.getPosition().z)); @@ -1072,13 +1072,13 @@ public class HarvesterService implements INetworkDispatch { constructionWaypoint.setStringAttribute("", ""); player.waypointAdd(constructionWaypoint); constructionWaypoint.setName(displayname); - constructionWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(actor.getPlanet().getName())); + constructionWaypoint.setPlanetCrc(CRC.StringtoCRC(actor.getPlanet().getName())); player.setLastSurveyWaypoint(constructionWaypoint); List attachments = new ArrayList(); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = true; - attachment.cellID = constructionWaypoint.getCellId(); + attachment.cellID = constructionWaypoint.getCellNumber(); attachment.color = (byte)1; attachment.name = displayname; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(actor.getPlanet().getName()); @@ -1111,7 +1111,7 @@ public class HarvesterService implements INetworkDispatch { public void enterStructurePlacementMode(CreatureObject actor, SWGObject object){ - if (!actor.getClient().isGM() && !core.terrainService.canBuildAtPosition(actor,actor.getPosition().x,actor.getPosition().z)){ + if (core.adminService.getAccessLevelFromDB(actor.getClient().getAccountId()) == null && !core.terrainService.canBuildAtPosition(actor,actor.getPosition().x,actor.getPosition().z)){ actor.sendSystemMessage("@player_structure:not_permitted", (byte) 0); return; } @@ -1240,7 +1240,7 @@ public class HarvesterService implements INetworkDispatch { WaypointObject constructionWaypoint = (WaypointObject)core.objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", actor.getPlanet(), harvester.getPosition().x, 0 ,harvester.getPosition().z); String displayname = "@installation_n:"+harvester.getStfName() + " " + counter; constructionWaypoint.setName(displayname); - constructionWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(actor.getPlanet().getName())); + constructionWaypoint.setPlanetCrc(CRC.StringtoCRC(actor.getPlanet().getName())); constructionWaypoint.setPosition(new Point3D(spawnCoordsX,0, spawnCoordsZ)); player.waypointAdd(constructionWaypoint); constructionWaypoint.setPosition(new Point3D(spawnCoordsX,0, spawnCoordsZ)); @@ -1249,7 +1249,7 @@ public class HarvesterService implements INetworkDispatch { constructionWaypoint.setStringAttribute("", ""); player.waypointAdd(constructionWaypoint); constructionWaypoint.setName(displayname); - constructionWaypoint.setPlanetCRC(engine.resources.common.CRC.StringtoCRC(actor.getPlanet().getName())); + constructionWaypoint.setPlanetCrc(CRC.StringtoCRC(actor.getPlanet().getName())); player.setLastSurveyWaypoint(constructionWaypoint); } diff --git a/src/services/spawn/DynamicSpawnArea.java b/src/services/spawn/DynamicSpawnArea.java index 6ff91997..db06d1ad 100644 --- a/src/services/spawn/DynamicSpawnArea.java +++ b/src/services/spawn/DynamicSpawnArea.java @@ -36,6 +36,7 @@ import resources.objects.creature.CreatureObject; import services.TerrainService; import services.SimulationService.MoveEvent; import tools.DevLog; +import engine.resources.config.Config; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -59,6 +60,12 @@ public class DynamicSpawnArea extends SpawnArea { @Override @Handler public void onEnter(EnterEvent event) { + + Config options = NGECore.getInstance().getOptions(); + + if (options != null && options.getInt("DO.ISOLATION.TESTS") > 0){ + return; + } SWGObject object = event.object; // ToDo: Mounted players must be handled too diff --git a/src/services/spawn/LairSpawnArea.java b/src/services/spawn/LairSpawnArea.java index 165c53b8..b41222f1 100644 --- a/src/services/spawn/LairSpawnArea.java +++ b/src/services/spawn/LairSpawnArea.java @@ -34,6 +34,7 @@ import resources.objects.creature.CreatureObject; import services.SimulationService.MoveEvent; import services.TerrainService; import services.ai.LairActor; +import engine.resources.config.Config; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -109,6 +110,12 @@ public class LairSpawnArea extends SpawnArea { @Handler public void onEnter(EnterEvent event) { + Config options = NGECore.getInstance().getOptions(); + + if (options != null && options.getInt("DO.ISOLATION.TESTS") > 0){ + return; + } + SWGObject object = event.object; if(object == null || !(object instanceof CreatureObject)) diff --git a/src/services/spawn/MixedSpawnArea.java b/src/services/spawn/MixedSpawnArea.java index e0b0a68b..8a4a5d43 100644 --- a/src/services/spawn/MixedSpawnArea.java +++ b/src/services/spawn/MixedSpawnArea.java @@ -36,6 +36,7 @@ import resources.objects.creature.CreatureObject; import services.TerrainService; import services.SimulationService.MoveEvent; import services.ai.LairActor; +import engine.resources.config.Config; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -61,7 +62,14 @@ public class MixedSpawnArea extends SpawnArea { @Override @Handler public void onEnter(EnterEvent event) { + + Config options = NGECore.getInstance().getOptions(); + if (options != null && options.getInt("DO.ISOLATION.TESTS") > 0){ + return; + } + + SWGObject object = event.object; // ToDo: Mounted players must be handled too //System.out.println("Entering object " + object.getClass().getName()); diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index 7060a877..efbf7844 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -62,6 +62,8 @@ public class MobileTemplate implements Cloneable { private List lootGroups = new ArrayList(); private String PCDTemplate=""; private String conversationFileName=""; + private boolean AIEnabled = true; + private boolean noAI = false; public Vector getTemplates() { @@ -369,5 +371,21 @@ public class MobileTemplate implements Cloneable { public void setConversationFileName(String conversationFileName) { this.conversationFileName = conversationFileName; } + + public boolean isAIEnabled() { + return AIEnabled; + } + + public void setAIEnabled(boolean aIEnabled) { + AIEnabled = aIEnabled; + } + + public boolean isNoAI() { + return noAI; + } + + public void setNoAI(boolean noAI) { + this.noAI = noAI; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index 0fc22032..f5d5aceb 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -32,12 +32,12 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Random; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; - import resources.common.collidables.CollidableBox; import resources.common.collidables.CollidableCircle; import resources.datatables.Options; @@ -75,8 +75,14 @@ public class SpawnService { public CreatureObject spawnCreature(String template, long objectId, String planetName, long cellId, float x, float y, float z, float qW, float qX, float qY, float qZ, short level) { - Planet planet = core.terrainService.getPlanetByName(planetName); MobileTemplate mobileTemplate = mobileTemplates.get(template); + return spawnCreature(mobileTemplate, objectId, planetName, cellId, x, y, z, qW, qX, qY, qZ, level); + } + + public CreatureObject spawnCreature(MobileTemplate mobileTemplate, long objectId, String planetName, long cellId, float x, float y, float z, float qW, float qX, float qY, float qZ, short level) { + + Planet planet = core.terrainService.getPlanetByName(planetName); + if(planet == null || mobileTemplate == null) return null; @@ -111,6 +117,9 @@ public class SpawnService { creature.setFaction(mobileTemplate.getFaction()); creature.setFactionStatus(mobileTemplate.getFactionStatus()); creature.setPvpBitmask(mobileTemplate.getPvpBitmask()); + + creature.updatePvpStatus(); + if (mobileTemplate.getCustomName()==null){ creature.setStfFilename("mob/creature_names"); // TODO: set other STFs for NPCs other than creatures -> DONE if (mobileTemplate.getStfFilename()!=null) @@ -159,6 +168,10 @@ public class SpawnService { defaultWeapon.setWeaponType(weaponTemplates.get(rnd).getWeaponType()); defaultWeapon.setMaxRange(weaponTemplates.get(rnd).getMaxRange()); defaultWeapon.setDamageType(weaponTemplates.get(rnd).getDamageType()); + if (defaultWeapon.getTemplate().contains("atst_ranged")){ + defaultWeapon.setStfFilename("theme_park_name"); + defaultWeapon.setStfName("at_st"); + } } if (weaponTemplates.get(rnd).getMinDamage() != 0 && weaponTemplates.get(rnd).getMaxDamage() != 0) { @@ -207,16 +220,26 @@ public class SpawnService { core.skillModService.addSkillMod(creature, "expertise_innate_protection_all", armor); } - AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); - creature.setAttachment("AI", actor); + if (mobileTemplate.isAIEnabled()){ + if (!mobileTemplate.isNoAI()){ // NoAI is for QuestGivers that don't fight to save resources + AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); + creature.setAttachment("AI", actor); + actor.setMobileTemplate(mobileTemplate); + } + } else { // AIEnabled is to dynamically switch the AI on later + AIActor actor = new AIActor(creature, creature.getPosition(), scheduler, false); + creature.setAttachment("AI", actor); + actor.setMobileTemplate(mobileTemplate); + } + + creature.setAttachment("radial_filename", "npc/mobile"); + if (mobileTemplate.getConversationFileName().length()>0){ creature.setAttachment("radial_filename", "object/conversation"); creature.setAttachment("conversationFile", mobileTemplate.getConversationFileName()); } else creature.setAttachment("radial_filename", "npc/mobile"); - actor.setMobileTemplate(mobileTemplate); - - + if(cell == null) { core.simulationService.add(creature, x, z, true); @@ -727,4 +750,13 @@ public class SpawnService { return mobileTemplates.get(template); } + public String getMobileTemplateName(MobileTemplate mobileTemplate) { + for (Entry entry : mobileTemplates.entrySet()) { + if (mobileTemplate.equals(entry.getValue())) { + return entry.getKey(); + } + } + return null; + } + } diff --git a/src/services/sui/SUIService.java b/src/services/sui/SUIService.java index 6b7a6fce..0165c5d1 100644 --- a/src/services/sui/SUIService.java +++ b/src/services/sui/SUIService.java @@ -37,6 +37,7 @@ import org.python.core.PyObject; import protocol.swg.ObjControllerMessage; import protocol.swg.ObjectMenuSelectMessage; import protocol.swg.SUICreatePageMessage; +import protocol.swg.SUICreateTimerBar; import protocol.swg.SUIEventNotification; import protocol.swg.SUIForceClosePageMessage; import protocol.swg.SUIUpdatePageMessage; @@ -490,10 +491,26 @@ public class SUIService implements INetworkDispatch { } SUICreatePageMessage create = new SUICreatePageMessage(window.getScript(), window.getWindowId(), window.getComponents(), rangeObjectId, range); + tools.CharonPacketUtils.printAnalysis(create.serialize(), "SUICreatePageMessage"); owner.getClient().getSession().write(create.serialize()); } + public void openTimerSUIWindow(SUIWindow window, String prompt, int startCount) { + + SWGObject owner = window.getOwner(); + + if(owner == null) + return; + + if(owner.getClient() == null || owner.getClient().getSession() == null) + return; + + SUICreateTimerBar create = new SUICreateTimerBar(window.getScript(), window.getWindowId(), prompt, startCount); + tools.CharonPacketUtils.printAnalysis(create.serialize(), "SUICreateTimerBar"); + owner.getClient().getSession().write(create.serialize()); + } + public void updateSUIWindow(SUIWindow window) { SWGObject owner = window.getOwner(); diff --git a/src/tools/DevLog.java b/src/tools/DevLog.java index c12a3aa5..e639083d 100644 --- a/src/tools/DevLog.java +++ b/src/tools/DevLog.java @@ -35,6 +35,10 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; +import services.ai.AIActor; +import services.ai.TurretAIActor; +import main.NGECore; + /** * @author Charon */ @@ -111,25 +115,109 @@ public class DevLog { if (debugEnable.get(developer)==1){ logMessage = "Devlog->"+developer+"->"+testarea+"-> "+message; DevLogQueuer logger = DevLogQueuer.getInstance(); - logger.log(logMessage); + if (logger!=null) + logger.log(logMessage); } } if (isFileLoggingEnabled(debugRequester)){ if (loggingSessionID>0){ DevLogQueuer logger = DevLogQueuer.getInstance(); - logger.log(logMessage,newFile); + if (logger!=null) + logger.log(logMessage,newFile); } else { createLog(); - DevLogQueuer logger = DevLogQueuer.getInstance(); - logger.log(logMessage,newFile); - loggingSessionID++; + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null){ + logger.log(logMessage,newFile); + loggingSessionID++; + } } } } + public static void debugoutai(AIActor actor, String debugRequester, String testarea, String message){ + if (NGECore.getInstance().aiService.getCheckAI()!=null && actor!=null){ + if (!(NGECore.getInstance().aiService.getCheckAI().getAttachment("AI") instanceof AIActor)) + return; + AIActor checkActor = (AIActor) NGECore.getInstance().aiService.getCheckAI().getAttachment("AI"); + if (checkActor==actor){ + String developer = System.getProperty("user.name"); + String logMessage = ""; + if (!debugRequester.equals(developer)) + return; + if (debugEnable.keySet().contains(developer)){ + + if (debugEnable.get(developer)==1){ + logMessage = "Devlog->"+developer+"->"+testarea+"-> "+message; + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null) + logger.log(logMessage); + } + } + + if (isFileLoggingEnabled(debugRequester)){ + if (loggingSessionID>0){ + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null) + logger.log(logMessage,newFile); + + } else { + createLog(); + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null){ + logger.log(logMessage,newFile); + loggingSessionID++; + } + } + } + } + } + } + + public static void debugoutai(TurretAIActor actor, String debugRequester, String testarea, String message){ + if (NGECore.getInstance().aiService.getCheckAI()!=null && actor!=null){ + if (!(NGECore.getInstance().aiService.getCheckAI().getAttachment("AI") instanceof TurretAIActor)) + return; + + TurretAIActor checkActor = (TurretAIActor) NGECore.getInstance().aiService.getCheckAI().getAttachment("AI"); + + if (checkActor==actor){ + String developer = System.getProperty("user.name"); + String logMessage = ""; + if (!debugRequester.equals(developer)) + return; + if (debugEnable.keySet().contains(developer)){ + + if (debugEnable.get(developer)==1){ + logMessage = "Devlog->"+developer+"->"+testarea+"-> "+message; + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null) + logger.log(logMessage); + } + } + + if (isFileLoggingEnabled(debugRequester)){ + if (loggingSessionID>0){ + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null) + logger.log(logMessage,newFile); + + } else { + createLog(); + DevLogQueuer logger = DevLogQueuer.getInstance(); + if (logger!=null){ + logger.log(logMessage,newFile); + loggingSessionID++; + } + } + } + } + } + } + public static void createLog(){ try { @@ -145,7 +233,7 @@ public class DevLog { newFile = Files.createFile(newFile); createHeader(newFile); } catch (IOException ex) { - System.out.println("Error creating file"); + System.out.println("Error creating file " + ex.getMessage()); } } diff --git a/src/tools/DevLogQueuer.java b/src/tools/DevLogQueuer.java index 205eb8cc..58a08f18 100644 --- a/src/tools/DevLogQueuer.java +++ b/src/tools/DevLogQueuer.java @@ -84,7 +84,7 @@ public class DevLogQueuer extends Thread { DevLog.appendToLog(str, path); } catch (Exception iex) { Thread.currentThread().interrupt(); - throw new RuntimeException("Unexpected interruption"); + throw new RuntimeException("Unexpected interruption -> Don't worry about it"); } }