diff --git a/ngengine_public.jar b/ngengine_public.jar index 3842feae..7c2fd4e0 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/scripts/buffs/me_buff_strength_3.py b/scripts/buffs/me_buff_strength_3.py new file mode 100644 index 00000000..e09c02e5 --- /dev/null +++ b/scripts/buffs/me_buff_strength_3.py @@ -0,0 +1,8 @@ +import sys + +def setup(core, actor, buff): + return + +def removeBuff(core, actor, buff): + return + \ No newline at end of file diff --git a/scripts/commands/faction.py b/scripts/commands/faction.py new file mode 100644 index 00000000..a99a074c --- /dev/null +++ b/scripts/commands/faction.py @@ -0,0 +1,24 @@ +from resources.objects.creature import CreatureObject +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + actorFaction = actor.getFaction() + + if commandString == ('imperial') and actorFaction != "imperial": + actor.setFaction('imperial') + actor.sendSystemMessage('You are aligned to the Imperial faction', 0) + return + + if commandString == ('rebel') and actorFaction != "rebel": + actor.setFaction('rebel') + actor.sendSystemMessage('You are aligned to the Rebellion', 0) + return + + if commandString == ('neutral') and actorFaction != "neutral": + actor.setFaction('neutral') + actor.sendSystemMessage('You aren\'t aligned to any faction.', 0) + return + return \ No newline at end of file diff --git a/scripts/commands/pvp.py b/scripts/commands/pvp.py index 7ed57c66..93e9051b 100644 --- a/scripts/commands/pvp.py +++ b/scripts/commands/pvp.py @@ -1,4 +1,5 @@ from resources.objects.creature import CreatureObject +from protocol.swg import UpdatePVPStatusMessage import sys def setup(): @@ -7,22 +8,67 @@ def setup(): def run(core, actor, target, commandString): actorFaction = actor.getFaction() actorStatus = actor.getFactionStatus() - if commandString.startswith('imperial') and actorFaction != "imperial": + pvpStatus = UpdatePVPStatusMessage(actor.getObjectId()) + + if commandString == ('imperial') and actorFaction != "imperial": actor.setFaction('imperial') return - if commandString.startswith('rebel') and actorFaction != "rebel": + if commandString == ('rebel') and actorFaction != "rebel": actor.setFaction('rebel') return - if actorStatus != 0 and actorStatus == 1: - actor.setFactionStatus(2) - actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) + if commandString == ('neutral') and actorFaction != "neutral": + actor.setFaction('neutral') return - if actorStatus == 2: + if actorStatus == 0 and actorFaction == "imperial": actor.setFactionStatus(1) + #print ("FactionStatus: " + str(actor.getFactionStatus())) + actor.sendSystemMessage('You are no longer On Leave.', 0) + return + + if actorStatus == 0 and actorFaction == "rebel": + actor.setFactionStatus(1) + #print ("FactionStatus: " + str(actor.getFactionStatus())) + actor.sendSystemMessage('You are no longer On Leave.', 0) + return + + if actorStatus == 1 and actorFaction == "imperial": + actor.setFactionStatus(2) + pvpStatus.setFaction(UpdatePVPStatusMessage.factionCRC.Imperial) + pvpStatus.setStatus(55) + actor.notifyObservers(pvpStatus.serialize(), True) + actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) + print ("FactionStatus: " + str(actor.getFactionStatus())) + return + + if actorStatus == 1 and actorFaction == "rebel": + actor.setFactionStatus(2) + pvpStatus.setFaction(UpdatePVPStatusMessage.factionCRC.Rebel) + pvpStatus.setStatus(55) + actor.notifyObservers(pvpStatus.serialize(), True) + actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) + print ("FactionStatus: " + str(actor.getFactionStatus())) + return + + if actorStatus == 2 and actorFaction == "imperial": + actor.setFactionStatus(1) + pvpStatus.setFaction(UpdatePVPStatusMessage.factionCRC.Imperial) + pvpStatus.setStatus(16) + actor.notifyObservers(pvpStatus.serialize(), True) actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) - return - return - \ No newline at end of file + print ("FactionStatus: " + str(actor.getFactionStatus())) + return + + if actorStatus == 2 and actorFaction == "rebel": + actor.setFactionStatus(1) + pvpStatus.setFaction(UpdatePVPStatusMessage.factionCRC.Rebel) + pvpStatus.setStatus(16) + actor.notifyObservers(pvpStatus.serialize(), True) + actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) + print ("FactionStatus: " + str(actor.getFactionStatus())) + return + + + return \ No newline at end of file diff --git a/scripts/commands/serverdestroyobject.py b/scripts/commands/serverdestroyobject.py index ee1725b7..5d3e2c60 100644 --- a/scripts/commands/serverdestroyobject.py +++ b/scripts/commands/serverdestroyobject.py @@ -7,8 +7,11 @@ def run(core, actor, target, commandString): if not target: return - - print 'Destroy Test' + + if target.getTemplate() == 'object/waypoint/shared_waypoint.iff': + actor.getSlottedObject('ghost').waypointRemove(target) + core.objectService.destroyObject(target) + return parent = target.getContainer() diff --git a/scripts/commands/setspeed.py b/scripts/commands/setspeed.py new file mode 100644 index 00000000..c73266de --- /dev/null +++ b/scripts/commands/setspeed.py @@ -0,0 +1,9 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + actor.setSpeedMultiplierBase(float(commandString)) + return + \ No newline at end of file diff --git a/scripts/commands/setwaypointactivestatus.py b/scripts/commands/setwaypointactivestatus.py new file mode 100644 index 00000000..e8ff2891 --- /dev/null +++ b/scripts/commands/setwaypointactivestatus.py @@ -0,0 +1,17 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + playerObject = actor.getSlottedObject('ghost') + waypointTarget = core.objectService.getObject(target.getObjectID()) + wp = playerObject.getWaypointFromList(target) + if wp.isActive() == True: + wp.setActive(False) + playerObject.waypointUpdate(wp) + return + else: + wp.setActive(True) + playerObject.waypointUpdate(wp) + return \ No newline at end of file diff --git a/scripts/commands/setwaypointname.py b/scripts/commands/setwaypointname.py new file mode 100644 index 00000000..33bc4507 --- /dev/null +++ b/scripts/commands/setwaypointname.py @@ -0,0 +1,12 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + playerObject = actor.getSlottedObject('ghost') + wp = playerObject.getWaypointFromList(target) + if wp is not None: + wp.setName(commandString) + playerObject.waypointUpdate(wp) + return \ No newline at end of file diff --git a/scripts/commands/tip.py b/scripts/commands/tip.py new file mode 100644 index 00000000..b0b4331c --- /dev/null +++ b/scripts/commands/tip.py @@ -0,0 +1,132 @@ +from resources.objects.creature import CreatureObject +from java.util import Date +from engine.resources.objects import SWGObject +from services.chat import ChatService +from services.chat import Mail +from services.sui import SUIWindow +from services.sui import SUIService +from services.sui.SUIWindow import Trigger +from services.sui.SUIService import MessageBoxType +from java.util import Vector +import sys + +# initialize global vars (happens at compile time) +commandArgs = "" +commandLength = 0 +actorID = long(0) +targetID = long(0) +tipAmount = 0 +tipAmountBank = 0 +bankSurcharge = 0 + + +def setup(): + return + +def run(core, actor, target, commandString): + + # set the global variables + global actorID + global targetID + global commandArgs + global commandLength + global tipAmount + global tipAmountBank + global bankSurcharge + + actorID = actor.getObjectID() + targetID = target.getObjectID() + commandArgs = commandString.split(" ") + commandLength = len(commandArgs) + tipAmount = commandArgs[0] + tipAmountBank = commandArgs[0] + bankSurcharge = int(0.05) * int(tipAmountBank) + + + #/tip int || /tip target int + if commandLength == 1: + + tipAmount = commandArgs[0] + actorFunds = actor.getCashCredits() + currentTarget = core.objectService.getObject(target.getObjectId()) + + if (actor.inRange(target.getPosition(), 100)): # 100 = 10m + if int(tipAmount) > 0 and int(tipAmount) <= 1000000: + if actorFunds >= int(tipAmount): + currentTarget.setCashCredits(int(tipAmount)) + actor.setCashCredits(actorFunds - int(tipAmount)) + + currentTarget.sendSystemMessage(actor.getCustomName() + ' tips you ' + tipAmount + ' credits.', 0) + actor.sendSystemMessage('You successfully tip ' + tipAmount + ' credits to ' + currentTarget.getCustomName() + '.', 0) + return + actor.sendSystemMessage('You lack the cash funds to tip ' + tipAmount + ' credits to ' + currentTarget.getCustomName() + '.', 0) + return + actor.sendSystemMessage('Invalid tip amount, set amount between 1 and 1,000,000 credits', 0) + return + actor.sendSystemMessage('Target is too far away. Try a wire bank transfer instead.', 0) + return + + #/tip target 30000000 bank + if commandLength == 2: + suiSvc = core.suiService + suiWindow = suiSvc.createMessageBox(MessageBoxType.MESSAGE_BOX_YES_NO, "@base_player:tip_wire_title", "@base_player:tip_wire_prompt", actor, actor, 10) + + returnParams = Vector() + returnParams.add('btnOk:Text') + returnParams.add('btnCancel:Text') + suiWindow.addHandler(0, '', Trigger.TRIGGER_OK, returnParams, handleBankTip) + suiWindow.addHandler(1, '', Trigger.TRIGGER_CANCEL, returnParams, handleBankTip) + + suiSvc.openSUIWindow(suiWindow) + return + return + +def handleBankTip(core, owner, eventType, returnList): + chatSvc = core.chatService + actorGlobal = core.objectService.getObject(actorID) + targetGlobal = core.objectService.getObject(targetID) + actorFunds = actorGlobal.getBankCredits() + totalLost = int(tipAmountBank) + bankSurcharge + + if eventType == 0: + if int(totalLost) > actorFunds: + actorGlobal.sendSystemMessage('You do not have ' + str(totalLost) + ' credits (surcharge included) to tip the desired amount to ' + targetGlobal.getCustomName() + '.', 0) + return + if int(tipAmount) > 0 and int(actorFunds) >= int(totalLost): + date = Date() + targetName = targetGlobal.getCustomName() + + targetMail = Mail() + targetMail.setMailId(chatSvc.generateMailId()) + targetMail.setTimeStamp((int) (date.getTime() / 1000)) + targetMail.setRecieverId(targetID) + targetMail.setStatus(Mail.NEW) + targetMail.setMessage(tipAmount + ' credits from ' + actorGlobal.getCustomName() + ' have been successfully delivered from escrow to your bank account') + targetMail.setSubject('@base_player:wire_mail_subject') + targetMail.setSenderName('bank') + + actorMail = Mail() + actorMail.setMailId(chatSvc.generateMailId()) + actorMail.setRecieverId(actorID) + actorMail.setStatus(Mail.NEW) + actorMail.setTimeStamp((int) (date.getTime() / 1000)) + actorMail.setMessage('An amount of ' + tipAmount + ' credits have been transfered from your bank to escrow. It will be delivered to ' + + targetGlobal.getCustomName() + ' as soon as possible.') + actorMail.setSubject('@base_player:wire_mail_subject') + actorMail.setSenderName('bank') + + targetGlobal.setBankCredits(int(tipAmount)) + actorGlobal.setBankCredits(int(actorFunds) - int(totalLost)) + actorGlobal.sendSystemMessage('You have successfully sent ' + tipAmount + ' bank credits to ' + targetGlobal.getCustomName(), 0) + targetGlobal.sendSystemMessage('You have successfully received ' + tipAmount + ' bank credits from ' + actorGlobal.getCustomName(), 0) + + chatSvc.storePersistentMessage(actorMail) + chatSvc.storePersistentMessage(targetMail) + chatSvc.sendPersistentMessageHeader(actorGlobal.getClient(), actorMail) + chatSvc.sendPersistentMessageHeader(targetGlobal.getClient(), targetMail) + return + + else: + actorGlobal.sendSystemMessage('You lack the bank funds to wire ' + tipAmount + ' bank funds to ' + targetGlobal.getCustomName() + '.', 0) + return + return diff --git a/scripts/commands/transferitemweapon.py b/scripts/commands/transferitemweapon.py index bd1efcd3..a480461a 100644 --- a/scripts/commands/transferitemweapon.py +++ b/scripts/commands/transferitemweapon.py @@ -12,6 +12,6 @@ def run(core, actor, target, commandString): print 'Weapon Test' oldContainer = target.getContainer() oldContainer.transferTo(actor, container, target) - + actor.setWeaponId(target.getObjectID()) return \ No newline at end of file diff --git a/scripts/commands/waypoint.py b/scripts/commands/waypoint.py new file mode 100644 index 00000000..3d7b5c12 --- /dev/null +++ b/scripts/commands/waypoint.py @@ -0,0 +1,84 @@ +from resources.objects.waypoint import WaypointObject +from engine.resources.scene import Point3D +from engine.resources.common import CRC +import sys + + +def run(core, actor, target, commandString): + validPlanets = ["tatooine", "naboo", "corellia", "rori", "talus", "yavin4", "endor", "lok", "dantooine", "dathomir", "kachirho", "etyyy", "khowir", "mustafar"] + validColors = ["blue", "green", "orange", "purple", "white", "yellow"] + crc = CRC + commandArgs = commandString.split(" ") + actorPlayer = actor.getSlottedObject("ghost") + + #/wp PLANET X Z Y COLOR NAME + if commandArgs[0] in validPlanets and commandArgs[4] in validColors: + try: + float(commandArgs[1]) + float(commandArgs[2]) + float(commandArgs[3]) + except ValueError: + return + planet = core.terrainService.getPlanetByName(commandArgs[0]) + waypoint = core.objectService.createObject('object/waypoint/shared_waypoint.iff', planet, float(commandArgs[1]), float(commandArgs[2]), float(commandArgs[3])) + waypoint.setActive(True) + waypoint.setColor(colorCheck(core, actor, target, commandString, commandArgs[4])) + name = commandString.split(" ", 5) + waypoint.setName(name[5]) + waypoint.setPlanetCRC(crc.StringtoCRC(planet.getName())) + actorPlayer.getWaypoints().add(waypoint) + actorPlayer.waypointAdd(waypoint) + actor.sendSystemMessage('A waypoint has been created in your datapad at your location.', 0) + return + + #/wp X Z Y NAME + if isFloat(commandArgs[0]) and isFloat(commandArgs[1]) and isFloat(commandArgs[2]): + waypoint = core.objectService.createObject('object/waypoint/shared_waypoint.iff', actor.getPlanet(), actor.getWorldPosition().x, actor.getWorldPosition().z, actor.getWorldPosition().y) + waypoint.setActive(True) + waypoint.setColor(WaypointObject.BLUE) + name = commandString.split(" ", 3) + waypoint.setName(name[3]) + waypoint.setPlanetCRC(crc.StringtoCRC(actor.getPlanet().getName())) + actorPlayer.getWaypoints().add(waypoint) + actorPlayer.waypointAdd(waypoint) + actor.sendSystemMessage('A waypoint has been created in your datapad at your location.', 0) + return + + #/wp NAME + else: + waypoint = core.objectService.createObject('object/waypoint/shared_waypoint.iff', actor.getPlanet(), actor.getWorldPosition().x, actor.getWorldPosition().z, actor.getWorldPosition().y) + waypoint.setActive(True) + waypoint.setColor(WaypointObject.BLUE) + waypoint.setName(commandString) + waypoint.setPlanetCRC(crc.StringtoCRC(actor.getPlanet().getName())) + actorPlayer.getWaypoints().add(waypoint) + actorPlayer.waypointAdd(waypoint) + actor.sendSystemMessage('A waypoint has been created in your datapad at your location.', 0) + return + + return + +def colorCheck(core, actor, target, commandString, validcolors): + if validcolors == "blue": + return WaypointObject.BLUE + if validcolors == "green": + return WaypointObject.GREEN + if validcolors == "orange": + return WaypointObject.ORANGE + if validcolors == "purple": + return WaypointObject.PURPLE + if validcolors == "white": + return WaypointObject.WHITE + if validcolors == "yellow": + return WaypointObject.YELLOW + return + +def isFloat(string): + try: + stringFloat = float(string) + except ValueError: + return False + + else: + return True + return \ No newline at end of file diff --git a/scripts/demo.py b/scripts/demo.py index 0176ca1e..adb7e3df 100644 --- a/scripts/demo.py +++ b/scripts/demo.py @@ -5,8 +5,34 @@ def CreateStartingCharacter(core, object): testObject = core.objectService.createObject('object/weapon/ranged/rifle/shared_rifle_t21.iff', object.getPlanet()) testObject.setCustomName('This is a Jython Rifle') testObject.setStringAttribute('crafter', 'Light') + testObject.setStringAttribute('cat_wpn_damage.wpn_damage_type', '@obj_attr_n:armor_eff_energy') + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_min', 425) + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_max', 1140) + object.addSkillMod('constitution_modified' , 350) + object.addSkillMod('strength_modified' , 350) + object.addSkillMod('precision_modified' , 350) + object.addSkillMod('luck_modified' , 350) + object.addSkillMod('agility_modified' , 350) + object.addSkillMod('stamina_modified' , 350) + object.addSkillMod('kinetic' , 10000) + object.addSkillMod('energy' , 10000) + object.addSkillMod('heat' , 6000) + object.addSkillMod('cold' , 6000) + object.addSkillMod('acid' , 6000) + object.addSkillMod('electricity' , 6000) + object.addSkillMod('combat_strikethrough_value' , 50) + object.addSkillMod('display_only_dodge' , 2000) + object.addSkillMod('display_only_parry' , 1000) + object.addSkillMod('display_only_strikethrough' , 500) + object.addSkillMod('display_only_critical' , 2500) + object.addSkillMod('display_only_evasion' , 1000) + object.addSkillMod('display_only_glancing_blow' , 750) + object.addSkillMod('display_only_block' , 2000) + object.addSkillMod('combat_block_value' , 0) inventory = object.getSlottedObject('inventory') + if not inventory: + return inventory.add(testObject) testClothing = core.objectService.createObject('object/tangible/wearables/cape/shared_cape_rebel_01.iff', object.getPlanet()) @@ -16,5 +42,59 @@ def CreateStartingCharacter(core, object): inventory.add(testClothing) inventory.add(testCloak) + profession = object.getSlottedObject('ghost').getProfession() + addProfessionAbilities(core, object, profession) + return + +def addProfessionAbilities(core, object, profession): + if profession == 'force_sensitive_1a': + testObject = core.objectService.createObject('object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gcw_s01_gen5.iff', object.getPlanet()) + testObject.setCustomName('Lightsaber') + testObject.setStringAttribute('crafter', 'Light') + testObject.setStringAttribute('cat_wpn_damage.wpn_damage_type', '@obj_attr_n:armor_eff_energy') + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_min', 600) + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_max', 1300) + inventory = object.getSlottedObject('inventory') + inventory.add(testObject) + + object.addAbility('fs_sweep_7') + object.addAbility('fs_drain_7') + object.addAbility('forceRun') + object.addAbility('fs_dm_cc_crit_5') + object.addAbility('fs_maelstrom_5') + object.addAbility('fs_ae_dm_cc_6') + object.addAbility('fs_sh_3') + object.addAbility('fs_dm_cc_6') + object.addAbility('fs_dm_7') + elif profession == 'medic_1a': + object.addAbility('me_bacta_bomb_5') + object.addAbility('me_bacta_grenade_5') + object.addAbility('me_bacta_ampule_6') + object.addAbility('me_ae_heal_6') + object.addAbility('me_dm_8') + object.addAbility('me_dm_dot_6') + object.addAbility('me_drag_1') + object.addAbility('me_rv_pvp_single') + object.addAbility('me_rv_area') + object.addAbility('me_rv_pvp_area') + object.addAbility('me_reckless_stimulation_6') + object.addAbility('me_sh_1') + object.addAbility('me_stasis_1') + object.addAbility('me_stasis_self_1') + object.addAbility('me_thyroid_rupture_1') + object.addAbility('me_traumatize_5') + object.addAbility('me_induce_insanity_1') + elif profession == 'bounty_hunter_1a': + object.addAbility('bh_shields_1') + object.addAbility('bh_dm_8') + object.addAbility('bh_sh_3') + object.addAbility('bh_armor_sprint_1') + object.addAbility('bh_prescience') + object.addAbility('bh_dm_crit_8') + object.addAbility('crippleShot') + object.addAbility('bh_fumble_6') + object.addAbility('bh_intimidate_6') + object.addAbility('bh_flawless_strike') + return diff --git a/scripts/static_map_locations.py b/scripts/static_map_locations.py index 36a776d7..dad930c8 100644 --- a/scripts/static_map_locations.py +++ b/scripts/static_map_locations.py @@ -1,21 +1,139 @@ -import sys - -def addLocations(core, planet): - - if planet.getName() == 'tatooine': - tatooineLocations(core, planet) - -def tatooineLocations(core, planet): - - mapService = core.mapService - - # Cities - - mapService.addLocation(planet, 'Bestine', -1290, -3590, 17, 0, 0) - mapService.addLocation(planet, 'Mos Espa', -2902, 2130, 17, 0, 0) - mapService.addLocation(planet, 'Mos Entha', 1291, 3138, 17, 0, 0) - mapService.addLocation(planet, 'Wayfar', -5124, -6530, 17, 0, 0) - mapService.addLocation(planet, 'Mos Eisley', 3528, -4804, 17, 0, 0) - mapService.addLocation(planet, 'Anchorhead', 40, -5348, 17, 0, 0) - +import sys + +def addLocations(core, planet): + + if planet.getName() == 'tatooine': + tatooineLocations(core, planet) + + if planet.getName() == 'corellia': + corelliaLocations(core, planet) + + if planet.getName() == 'naboo': + nabooLocations(core, planet) + + if planet.getName() == 'rori': + roriLocations(core, planet) + + if planet.getName() == 'endor': + endorLocations(core, planet) + + if planet.getName() == 'talus': + talusLocations(core, planet) + + if planet.getName() == 'yavin4': + yavin4Locations(core, planet) + + if planet.getName() == 'dantooine': + dantooineLocations(core, planet) + + if planet.getName() == 'dathomir': + dathomirLocations(core, planet) + + if planet.getName() == 'lok': + lokLocations(core, planet) + +def tatooineLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Bestine', -1290, -3590, 17, 0, 0) + mapService.addLocation(planet, 'Mos Espa', -2902, 2130, 17, 0, 0) + mapService.addLocation(planet, 'Mos Entha', 1291, 3138, 17, 0, 0) + mapService.addLocation(planet, 'Wayfar', -5124, -6530, 17, 0, 0) + mapService.addLocation(planet, 'Mos Eisley', 3528, -4804, 17, 0, 0) + mapService.addLocation(planet, 'Anchorhead', 40, -5348, 17, 0, 0) + +def corelliaLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Coronet', -178, -4504, 17, 0, 0) + mapService.addLocation(planet, 'Tyrena', -5140, 2450, 17, 0, 0) + mapService.addLocation(planet, 'Bela Vistal', 6766, -5692, 17, 0, 0) + mapService.addLocation(planet, 'Kor Vella', -3420, 3146, 17, 0, 0) + mapService.addLocation(planet, 'Doaba Guerfel', 3274, 5582, 17, 0, 0) + mapService.addLocation(planet, 'Vreni Island', -5538, 6176, 17, 0, 0) + +def nabooLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Theed', -5488, 4380, 17, 0, 0) + mapService.addLocation(planet, 'Keren', 1888, 2700, 17, 0, 0) + mapService.addLocation(planet, 'Moeina', 4836, -4830.5, 17, 0, 0) + mapService.addLocation(planet, 'Deeja Park', -4686, -1375, 17, 0, 0) + mapService.addLocation(planet, 'Kaadara', 5288, 6687, 17, 0, 0) + +def roriLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Narmle', -5140, -2368, 17, 0, 0) + mapService.addLocation(planet, 'Restuss', 5318, 5680, 17, 0, 0) + mapService.addLocation(planet, 'a Rebel outpost', 3677, -6447, 17, 0, 0) + +def endorLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'an outpost', -905, 1584, 17, 0, 0) + +def talusLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Dearic', 422, -3004, 17, 0, 0) + mapService.addLocation(planet, 'Nashal', 4163, 5220, 17, 0, 0) + mapService.addLocation(planet, 'an Imperial outpost', -2178, 2300, 17, 0, 0) + +def yavin4Locations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Mining Outpost', -312, 4865, 17, 0, 0) + mapService.addLocation(planet, 'Labor Outpost', -6925, -5707, 17, 0, 0) + +def dantooineLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'a mining outpost', -640, 2486, 17, 0, 0) + mapService.addLocation(planet, 'a pirate outpost', 1588, -6399, 17, 0, 0) + mapService.addLocation(planet, 'an Imperial outpost', -4224, -2400, 17, 0, 0) + +def dathomirLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'a restricted area', -6358, 930, 17, 0, 0) + mapService.addLocation(planet, 'Trade Outpost', 599, 3046, 17, 0, 0) + mapService.addLocation(planet, 'Science Outpost', -85, -1600, 17, 0, 0) + +def lokLocations(core, planet): + + mapService = core.mapService + + # Cities + + mapService.addLocation(planet, 'Nym\'s Stronghold', 440, 5029, 17, 0, 0) + mapService.addLocation(planet, 'an Imperial outpost', -1920, -3084, 17, 0, 0) + \ No newline at end of file diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 34602e3f..c2cc998d 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -22,6 +22,8 @@ package main; import java.io.IOException; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Vector; @@ -31,13 +33,17 @@ import java.util.concurrent.ConcurrentHashMap; import resources.common.RadialOptions; import resources.objects.creature.CreatureObject; import services.AttributeService; +import services.BuffService; import services.CharacterService; import services.ConnectionService; import services.LoginService; +import services.PlayerService; import services.ScriptService; import services.SimulationService; import services.TerrainService; import services.chat.ChatService; +import services.combat.CombatService; +import services.command.CombatCommand; import services.command.CommandService; import services.gcw.GCWService; import services.guild.GuildService; @@ -101,6 +107,9 @@ public class NGECore { public GuildService guildService; public GCWService gcwService; public TradeService tradeService; + public CombatService combatService; + public PlayerService playerService; + public BuffService buffService; // Login Server public NetworkDispatch loginDispatch; @@ -129,7 +138,7 @@ public class NGECore { databaseConnection.connect(config.getString("DB.URL"), config.getString("DB.NAME"), config.getString("DB.USER"), config.getString("DB.PASS"), "postgresql"); databaseConnection2 = new DatabaseConnection(); - + setGalaxyStatus(1); creatureODB = new ObjectDatabase("creature", true, false, true); mailODB = new ObjectDatabase("mails", true, false, true); @@ -147,7 +156,9 @@ public class NGECore { chatService = new ChatService(this); attributeService = new AttributeService(this); suiService = new SUIService(this); - + combatService = new CombatService(this); + playerService = new PlayerService(this); + buffService = new BuffService(this); // Ping Server try { PingServer pingServer = new PingServer(config.getInt("PING.PORT")); @@ -172,6 +183,7 @@ public class NGECore { zoneDispatch.addService(chatService); zoneDispatch.addService(suiService); zoneDispatch.addService(mapService); + zoneDispatch.addService(playerService); zoneServer = new MINAServer(zoneDispatch, config.getInt("ZONE.PORT")); zoneServer.start(); @@ -196,6 +208,8 @@ public class NGECore { didServerCrash = false; System.out.println("Started Server."); + setGalaxyStatus(2); + } @@ -248,6 +262,21 @@ public class NGECore { } + public void setGalaxyStatus(int statusId) { + + int galaxyId = config.getInt("GALAXY_ID"); + + try { + PreparedStatement ps = databaseConnection.preparedStatement("UPDATE \"connectionServers\" SET \"statusId\"=? WHERE \"galaxyId\"=?"); + ps.setInt(1, statusId); + ps.setInt(2, galaxyId); + ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + + } + /* * ---------- Getter methods for NGECore ---------- */ diff --git a/src/protocol/swg/ChatPersistentMessageToClient.java b/src/protocol/swg/ChatPersistentMessageToClient.java index 08f79a3d..3db681b6 100644 --- a/src/protocol/swg/ChatPersistentMessageToClient.java +++ b/src/protocol/swg/ChatPersistentMessageToClient.java @@ -22,8 +22,9 @@ package protocol.swg; import java.nio.ByteOrder; - +import java.util.List; import org.apache.mina.core.buffer.IoBuffer; +import services.chat.WaypointAttachment; public class ChatPersistentMessageToClient extends SWGMessage { @@ -36,8 +37,9 @@ public class ChatPersistentMessageToClient extends SWGMessage { private String subject; private byte status; private int timestamp; + private List attachments; - public ChatPersistentMessageToClient(String sender, String galaxyName, int mailId, byte requestTypeFlag, String message, String subject, byte status, int timestamp) { + public ChatPersistentMessageToClient(String sender, String galaxyName, int mailId, byte requestTypeFlag, String message, String subject, byte status, int timestamp, List attachments) { this.sender = sender; this.galaxyName = galaxyName; @@ -47,6 +49,7 @@ public class ChatPersistentMessageToClient extends SWGMessage { this.subject = subject; this.status = status; this.timestamp = timestamp; + this.attachments = attachments; } @@ -60,7 +63,7 @@ public class ChatPersistentMessageToClient extends SWGMessage { public IoBuffer serialize() { IoBuffer result = IoBuffer.allocate(41 + sender.length() + galaxyName.length() + message.length() * 2 + subject.length() * 2).order(ByteOrder.LITTLE_ENDIAN); - + result.setAutoExpand(true); result.putShort((short) 2); result.putInt(0x08485E17); result.put(getAsciiString(sender)); @@ -75,12 +78,40 @@ public class ChatPersistentMessageToClient extends SWGMessage { result.put(getUnicodeString(message)); result.put(getUnicodeString(subject)); - result.putInt(0); // attachements doing later when waypoints work + + if(requestTypeFlag == 1 || attachments.size() == 0) + result.putInt(0); + else if(requestTypeFlag == 0 && attachments.size() > 0){ + + int position = result.position(); + result.putInt(0); + + for(WaypointAttachment attachment : attachments) { + + result.putInt(0); + result.putFloat(attachment.positionX); + result.putFloat(attachment.positionY); + result.putFloat(attachment.positionZ); + result.putLong(0); + result.putInt(attachment.planetCRC); + result.put(getUnicodeString(attachment.name)); + result.putLong(attachment.cellID); + result.put(attachment.color); + result.put((byte) (attachment.active ? 1 : 0)); + + } + + result.putInt(position, (result.position() - position - 4) / 2); + + } result.put(status); result.putInt(timestamp); 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/ChatPersistentMessageToServer.java b/src/protocol/swg/ChatPersistentMessageToServer.java index 40b9d142..23be8a29 100644 --- a/src/protocol/swg/ChatPersistentMessageToServer.java +++ b/src/protocol/swg/ChatPersistentMessageToServer.java @@ -23,8 +23,10 @@ package protocol.swg; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; - +import java.util.ArrayList; +import java.util.List; import org.apache.mina.core.buffer.IoBuffer; +import services.chat.WaypointAttachment; public class ChatPersistentMessageToServer extends SWGMessage { @@ -33,6 +35,7 @@ public class ChatPersistentMessageToServer extends SWGMessage { private int counter; private String subject; private String recipient; + private List waypointAttachments = new ArrayList(); @Override public void deserialize(IoBuffer buffer) { @@ -47,11 +50,52 @@ public class ChatPersistentMessageToServer extends SWGMessage { setMessage(new String(ByteBuffer.allocate(size * 2).put(buffer.array(), buffer.position(), size * 2).array(), "UTF-16LE")); buffer.position(buffer.position() + size * 2); - int attachmentsSize = buffer.getInt(); // TODO: Implement when waypoints are done + int attachmentsSize = buffer.getInt() * 2; - while(attachmentsSize > 0) { + /*while(attachmentsSize > 0) { buffer.get(); --attachmentsSize; + }*/ + + if(attachmentsSize > 0) { + + int position = buffer.position(); + + while(buffer.position() < position + attachmentsSize) { + + short appendByte = buffer.getShort(); + buffer.get(); + int type = buffer.getInt(); + + if(type == 0xFFFFFFFD) { + + WaypointAttachment waypoint = new WaypointAttachment(); + + buffer.getInt(); // unk 0 + waypoint.positionX = buffer.getFloat(); + waypoint.positionY = buffer.getFloat(); + waypoint.positionZ = buffer.getFloat(); + buffer.getLong(); // unk + waypoint.planetCRC = buffer.getInt(); + size = buffer.getInt(); + waypoint.name = new String(ByteBuffer.allocate(size * 2).put(buffer.array(), buffer.position(), size * 2).array(), "UTF-16LE"); + buffer.position(buffer.position() + size * 2); + waypoint.cellID = buffer.getLong(); + waypoint.color = buffer.get(); + byte active = buffer.get(); + if(active == 1) + waypoint.active = true; + else + waypoint.active = false; + + waypointAttachments.add(waypoint); + + if(appendByte > 0) + buffer.get(); + + } + } + } setCounter(buffer.getInt()); @@ -110,5 +154,15 @@ public class ChatPersistentMessageToServer extends SWGMessage { public void setCounter(int counter) { this.counter = counter; } + + public List getWaypointAttachments() { + return waypointAttachments; + } + + public void setWaypointAttachments(List waypointAttachments) { + this.waypointAttachments = waypointAttachments; + } + + } diff --git a/src/protocol/swg/ClientCreateCharacter.java b/src/protocol/swg/ClientCreateCharacter.java index 3acde5b6..c11204f4 100644 --- a/src/protocol/swg/ClientCreateCharacter.java +++ b/src/protocol/swg/ClientCreateCharacter.java @@ -79,7 +79,6 @@ public class ClientCreateCharacter extends SWGMessage { hairObject = new String(ByteBuffer.allocate(size).put(buffer.array(), buffer.position(), size).array(), "US-ASCII"); buffer.position(buffer.position() + size); length = buffer.getShort(); - System.out.println("Position: " + buffer.position()); hairCustomization = new byte[length]; buffer.get(hairCustomization); size = buffer.getShort(); diff --git a/src/protocol/swg/CmdStartScene.java b/src/protocol/swg/CmdStartScene.java index 0e8ec8b5..52d1eb36 100644 --- a/src/protocol/swg/CmdStartScene.java +++ b/src/protocol/swg/CmdStartScene.java @@ -71,7 +71,7 @@ public class CmdStartScene extends SWGMessage { result.put(getAsciiString(sharedRaceTemplate)); result.putLong(time); - result.put(new byte[] { (byte)0x8B, (byte)0xC0, (byte)0xEA, (byte)0x4E }); + result.put(new byte[] { (byte)0x8E, (byte)0xB5, (byte)0xEA, (byte)0x4E }); return result.flip(); } diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index 7792009c..e307d7c2 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -41,6 +41,7 @@ public class ObjControllerMessage extends SWGMessage { public static final int DATA_TRANSFORM = 0x0071; public static final int SPACIAL_CHAT = 0x00F4; public static final int COMMAND_ENQUEUE = 0x0116; + public static final int COMMAND_ENQUEUE_REMOVE = 0x0117; public static final int USE_OBJECT = 0x0126; public static final int PLAYER_EMOTE = 0x012E; public static final int DATA_TRANSFORM_WITH_PARENT = 0x00F1; @@ -49,6 +50,8 @@ public class ObjControllerMessage extends SWGMessage { public static final int POSTURE = 0x0131; public static final int SIT_ON_OBJECT = 0x013B; public static final int OBJECT_MENU_RESPONSE = 0x0147; + public static final int SHOW_FLY_TEXT = 0x01BD; + public static final int START_TASK = 0x448; public ObjControllerMessage() { diff --git a/src/protocol/swg/SceneCreateObjectByCrc.java b/src/protocol/swg/SceneCreateObjectByCrc.java index 5b3921a0..f5429415 100644 --- a/src/protocol/swg/SceneCreateObjectByCrc.java +++ b/src/protocol/swg/SceneCreateObjectByCrc.java @@ -74,7 +74,6 @@ public class SceneCreateObjectByCrc extends SWGMessage { result.putFloat(pZ); result.putInt(crc); result.put(flags); - result.flip(); - return result; + return result.flip(); } } diff --git a/src/protocol/swg/SceneDestroyObject.java b/src/protocol/swg/SceneDestroyObject.java index 75edc1d5..f0716d84 100644 --- a/src/protocol/swg/SceneDestroyObject.java +++ b/src/protocol/swg/SceneDestroyObject.java @@ -39,12 +39,12 @@ public class SceneDestroyObject extends SWGMessage { } public IoBuffer serialize() { - IoBuffer result = IoBuffer.allocate(15).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer result = IoBuffer.allocate(14).order(ByteOrder.LITTLE_ENDIAN); result.putShort((short)3); result.putInt(0x4D45D504); result.putLong(objectId); - return result; + return result.flip(); } } diff --git a/src/protocol/swg/UnkByteFlag.java b/src/protocol/swg/UnkByteFlag.java index 55710bf9..ddaa565f 100644 --- a/src/protocol/swg/UnkByteFlag.java +++ b/src/protocol/swg/UnkByteFlag.java @@ -37,7 +37,7 @@ public class UnkByteFlag extends SWGMessage { @Override public IoBuffer serialize() { IoBuffer result = IoBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN); - System.out.println("test"); + result.putShort((short) 2); result.putInt(0x7102B15F); result.put((byte) 1); diff --git a/src/protocol/swg/UpdatePVPStatusMessage.java b/src/protocol/swg/UpdatePVPStatusMessage.java index 152ef4ca..c5704b61 100644 --- a/src/protocol/swg/UpdatePVPStatusMessage.java +++ b/src/protocol/swg/UpdatePVPStatusMessage.java @@ -31,10 +31,10 @@ public class UpdatePVPStatusMessage extends SWGMessage { private long objectId; private int pvpStatus; + private int faction; - public UpdatePVPStatusMessage(long objectId, int pvpStatus) { + public UpdatePVPStatusMessage(long objectId) { this.objectId = objectId; - this.pvpStatus = pvpStatus; } public void deserialize(IoBuffer data) { @@ -47,9 +47,21 @@ public class UpdatePVPStatusMessage extends SWGMessage { result.putShort((short)4); result.putInt(0x08A1C126); result.putInt(pvpStatus); - result.putInt(0); // faction crc + result.putInt(faction); result.putLong(objectId); result.flip(); return result; } + public enum factionCRC {; + public static final int Neutral = 0; + public static final int Imperial = 0xDB4ACC54; + public static final int Rebel = 0x16148850; + } + public void setFaction(int factionCRC) { + this.faction = factionCRC; + } + + public void setStatus(int status) { + this.pvpStatus = status; + } } diff --git a/src/protocol/swg/UpdateTransformMessage.java b/src/protocol/swg/UpdateTransformMessage.java index 555e2a2b..8ed53713 100644 --- a/src/protocol/swg/UpdateTransformMessage.java +++ b/src/protocol/swg/UpdateTransformMessage.java @@ -36,9 +36,8 @@ public class UpdateTransformMessage extends SWGMessage { private int movementCounter; private byte direction; private float speed; - private byte combatFlag; - public UpdateTransformMessage(long objectId, short x, short y, short z, int movementCounter, byte direction, float speed, byte combatFlag) { + public UpdateTransformMessage(long objectId, short x, short y, short z, int movementCounter, byte direction, float speed) { this.objectId = objectId; this.x = x; this.y = y; @@ -46,7 +45,6 @@ public class UpdateTransformMessage extends SWGMessage { this.movementCounter = movementCounter; this.direction = direction; this.speed = speed; - this.combatFlag = combatFlag; } public void deserialize(IoBuffer data) { @@ -65,8 +63,8 @@ public class UpdateTransformMessage extends SWGMessage { result.putInt(movementCounter+1); result.put((byte) speed); result.put((byte) direction); + result.put((byte) 1); result.put((byte) 0); - result.put(combatFlag); result.flip(); return result; } diff --git a/src/protocol/swg/UpdateTransformWithParentMessage.java b/src/protocol/swg/UpdateTransformWithParentMessage.java index fd3ca8e9..c490fa73 100644 --- a/src/protocol/swg/UpdateTransformWithParentMessage.java +++ b/src/protocol/swg/UpdateTransformWithParentMessage.java @@ -37,9 +37,8 @@ public class UpdateTransformWithParentMessage extends SWGMessage { private int movementCounter; private byte direction; private float speed; - private byte combatFlag; - public UpdateTransformWithParentMessage(long objectId, long cellId, short x, short y, short z, int movementCounter, byte direction, float speed, byte combatFlag) { + public UpdateTransformWithParentMessage(long objectId, long cellId, short x, short y, short z, int movementCounter, byte direction, float speed) { this.objectId = objectId; this.cellId = cellId; this.x = x; @@ -48,7 +47,6 @@ public class UpdateTransformWithParentMessage extends SWGMessage { this.movementCounter = movementCounter; this.direction = direction; this.speed = speed; - this.combatFlag = combatFlag; } public void deserialize(IoBuffer data) { @@ -68,7 +66,8 @@ public class UpdateTransformWithParentMessage extends SWGMessage { result.putInt(movementCounter+1); result.put((byte) speed); result.put(direction); - result.put(combatFlag); + result.put((byte) 1); + result.put((byte) 0); result.flip(); return result; } diff --git a/src/protocol/swg/objectControllerObjects/CombatAction.java b/src/protocol/swg/objectControllerObjects/CombatAction.java index 6a119b38..41087f21 100644 --- a/src/protocol/swg/objectControllerObjects/CombatAction.java +++ b/src/protocol/swg/objectControllerObjects/CombatAction.java @@ -33,12 +33,14 @@ public class CombatAction extends ObjControllerObject{ private long attackerId; private long weaponId; private long defenderId; + private int commandCRC; - public CombatAction(int actionCRC, long attackerId, long weaponId, long defenderId) { + public CombatAction(int actionCRC, long attackerId, long weaponId, long defenderId, int commandCRC) { this.actionCRC = actionCRC; this.attackerId = attackerId; this.weaponId = weaponId; this.defenderId = defenderId; + this.commandCRC = commandCRC; } public void deserialize(IoBuffer data) { @@ -46,7 +48,8 @@ public class CombatAction extends ObjControllerObject{ } public IoBuffer serialize() { - IoBuffer result = IoBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN); + + IoBuffer result = IoBuffer.allocate(60).order(ByteOrder.LITTLE_ENDIAN); result.putInt(ObjControllerMessage.COMBAT_ACTION); @@ -56,17 +59,23 @@ public class CombatAction extends ObjControllerObject{ result.putLong(attackerId); result.putLong(weaponId); result.put((byte) 0); + result.put((byte) 0x10); + result.put((byte) 0); + result.putInt(commandCRC); + result.put((byte) 0); + result.putShort((short) 1); + result.putLong(defenderId); + result.put((byte) 0); result.put((byte) 1); result.put((byte) 0); - byte[] unkdata = new byte[] { - 0x2B, (byte) 0x87, 0x64, (byte) 0xA1, 0x01, 0x15, 0x02, (byte) 0x97, (byte) 0xC5, 0x00, 0x00, (byte) 0xD0, 0x40, 0x6F, 0x16, (byte) 0x80, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - result.put(unkdata); + byte[] unkdata2 = new byte[] { (byte) 0, 0, 0 }; + result.put(unkdata2); + + return result.flip(); - return result; } public CombatAction clone() { - return new CombatAction(actionCRC, attackerId, weaponId, defenderId); + return new CombatAction(actionCRC, attackerId, weaponId, defenderId, actionCRC); } } diff --git a/src/protocol/swg/objectControllerObjects/CommandEnqueueRemove.java b/src/protocol/swg/objectControllerObjects/CommandEnqueueRemove.java new file mode 100644 index 00000000..23a28342 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/CommandEnqueueRemove.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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; + +public class CommandEnqueueRemove extends ObjControllerObject { + + private long objectId; + private int actionCounter; + + public CommandEnqueueRemove(long objectId, int actionCounter) { + this.objectId = objectId; + this.actionCounter = actionCounter; + } + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(32).order(ByteOrder.LITTLE_ENDIAN); + + result.putInt(ObjControllerMessage.COMMAND_ENQUEUE_REMOVE); + result.putLong(objectId); + result.putInt(0); + result.putInt(actionCounter); + result.putLong(0); + result.putInt(0); + + return result.flip(); + + } + +} diff --git a/src/protocol/swg/objectControllerObjects/DataTransform.java b/src/protocol/swg/objectControllerObjects/DataTransform.java index a86fccc0..3b8381e5 100644 --- a/src/protocol/swg/objectControllerObjects/DataTransform.java +++ b/src/protocol/swg/objectControllerObjects/DataTransform.java @@ -118,7 +118,7 @@ public class DataTransform extends ObjControllerObject { result.putInt(0); result.putInt(0); - result.putInt(movementIndex+1); + result.putInt(movementIndex); result.putFloat(0); result.putFloat(yOrientation); //xRot @@ -131,7 +131,7 @@ public class DataTransform extends ObjControllerObject { result.putFloat(speed); //unk result.putFloat(0); //unk - result.put((byte)0x01); + result.put((byte)0x00); return result.flip(); } diff --git a/src/protocol/swg/objectControllerObjects/ObjectMenuResponse.java b/src/protocol/swg/objectControllerObjects/ObjectMenuResponse.java index 90eb1938..b4450dc9 100644 --- a/src/protocol/swg/objectControllerObjects/ObjectMenuResponse.java +++ b/src/protocol/swg/objectControllerObjects/ObjectMenuResponse.java @@ -77,8 +77,7 @@ public class ObjectMenuResponse extends ObjControllerObject { for(RadialOptions radialOption : radialOptions) { result.put(counter++); result.put(radialOption.getParentId()); - result.put(radialOption.getOptionId()); - result.put((byte) 0); + result.putShort(radialOption.getOptionId()); result.put(radialOption.getOptionType()); if(radialOption.getDescription().length() > 0) diff --git a/src/protocol/swg/objectControllerObjects/ShowFlyText.java b/src/protocol/swg/objectControllerObjects/ShowFlyText.java new file mode 100644 index 00000000..083d97b2 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/ShowFlyText.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * 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; + +public class ShowFlyText extends ObjControllerObject { + + private long recieverId; + private long objectId; + private String stfFile; + private String stfString; + private float scale; + private float color; + + public ShowFlyText(long recieverId, long objectId, String stfFile, String stfString, float scale, float color) { + this.recieverId = recieverId; + this.objectId = objectId; + this.stfFile = stfFile; + this.stfString = stfString; + this.scale = scale; + this.color = color; + } + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(47 + stfFile.length() + stfString.length()).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); + + result.putInt(ObjControllerMessage.SHOW_FLY_TEXT); + result.putLong(recieverId); + result.putInt(0); + result.putLong(objectId); + + result.put(getAsciiString(stfFile)); + result.putInt(0); + result.put(getAsciiString(stfString)); + result.putInt(0); + result.putFloat(scale); + result.putFloat(color); // color + result.putShort((short) 0); + result.put((byte) 0); + + return result.flip(); + + } + +} diff --git a/src/protocol/swg/objectControllerObjects/StartTask.java b/src/protocol/swg/objectControllerObjects/StartTask.java new file mode 100644 index 00000000..c8cdd408 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/StartTask.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; + +public class StartTask extends ObjControllerObject { + + private int actionCounter; + private long objectId; + private int commandCRC; + + public StartTask(int actionCounter, long objectId, int commandCRC) { + this.actionCounter = actionCounter; + this.objectId = objectId; + this.commandCRC = commandCRC; + } + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(33).order(ByteOrder.LITTLE_ENDIAN); + + result.putInt(ObjControllerMessage.START_TASK); + + result.putLong(objectId); + result.putInt(0); + result.put((byte) 0); + result.putInt(actionCounter); + result.putLong(0); + result.putInt(commandCRC); + + return result.flip(); + + } + +} diff --git a/src/resources/common/FileUtilities.java b/src/resources/common/FileUtilities.java index 86904bc7..b9fa36d8 100644 --- a/src/resources/common/FileUtilities.java +++ b/src/resources/common/FileUtilities.java @@ -21,6 +21,7 @@ ******************************************************************************/ package resources.common; +import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; @@ -36,6 +37,13 @@ public class FileUtilities { lnr.close(); return numberOfLines; + } + + public static boolean doesFileExist(String filePath) { + + File file = new File(filePath); + + return file.exists(); } diff --git a/src/resources/common/RadialOptions.java b/src/resources/common/RadialOptions.java index 03b4e20e..409766ab 100644 --- a/src/resources/common/RadialOptions.java +++ b/src/resources/common/RadialOptions.java @@ -277,11 +277,11 @@ public class RadialOptions { public static int StopManufacture = 252; private byte parentId; - private byte optionId; + private short optionId; private byte optionType; private String description; - public RadialOptions(byte parentId, byte optionId, byte optionType, String description) { + public RadialOptions(byte parentId, short optionId, byte optionType, String description) { this.setParentId(parentId); this.setOptionId(optionId); this.setOptionType(optionType); @@ -300,11 +300,11 @@ public class RadialOptions { this.parentId = parentId; } - public byte getOptionId() { + public short getOptionId() { return optionId; } - public void setOptionId(byte optionId) { + public void setOptionId(short optionId) { this.optionId = optionId; } diff --git a/src/resources/objects/Buff.java b/src/resources/objects/Buff.java new file mode 100644 index 00000000..f66d61a3 --- /dev/null +++ b/src/resources/objects/Buff.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * 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 resources.objects; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.buffer.SimpleBufferAllocator; + +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; + +import engine.clientdata.ClientFileManager; +import engine.clientdata.visitors.DatatableVisitor; +import engine.resources.common.CRC; + +@Persistent(version=3) +public class Buff implements IListObject { + + @NotPersistent + private SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); + private float duration; + private String buffName; + private long ownerId; + private String effect1Name, effect2Name, effect3Name, effect4Name, effect5Name; + private float effect1Value, effect2Value, effect3Value, effect4Value, effect5Value; + private String particleEffect; + private boolean isDebuff; + private boolean removeOnDeath; + private boolean isRemovableByPlayer; + private int maxStacks; + private boolean isPersistent; + private boolean removeOnRespec; + private boolean aiRemoveOnEndCombat; + private boolean decayOnPvPDeath; + private long startTime; + private int totalPlayTime; + + public Buff(String buffName, long ownerId) { + + this.buffName = buffName; + this.ownerId = ownerId; + + DatatableVisitor visitor; + + try { + + visitor = ClientFileManager.loadFile("datatables/buff/buff.iff", DatatableVisitor.class); + for(int i = 0; i < visitor.getRowCount(); i++) { + + if(visitor.getObject(i, 0) != null) + if(((String) visitor.getObject(i, 0)).equalsIgnoreCase(buffName)) { + + duration = (Float) visitor.getObject(i, 6); + effect1Name = (String) visitor.getObject(i, 7); + effect1Value = (Float) visitor.getObject(i, 8); + effect2Name = (String) visitor.getObject(i, 9); + effect2Value = (Float) visitor.getObject(i, 10); + effect3Name = (String) visitor.getObject(i, 11); + effect3Value = (Float) visitor.getObject(i, 12); + effect4Name = (String) visitor.getObject(i, 13); + effect4Value = (Float) visitor.getObject(i, 14); + effect5Name = (String) visitor.getObject(i, 15); + effect5Value = (Float) visitor.getObject(i, 16); + particleEffect = (String) visitor.getObject(i, 19); + isDebuff = (Boolean) visitor.getObject(i, 22); + removeOnDeath = (Integer) visitor.getObject(i, 25) != 0; + isRemovableByPlayer = (Integer) visitor.getObject(i, 26) != 0; + maxStacks = (Integer) visitor.getObject(i, 28); + isPersistent = (Integer) visitor.getObject(i, 29) != 0; + removeOnRespec = (Integer) visitor.getObject(i, 31) != 0; + aiRemoveOnEndCombat = (Integer) visitor.getObject(i, 32) != 0; + decayOnPvPDeath = (Integer) visitor.getObject(i, 33) != 0; + + } + + } + + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + + + + + } + + public Buff() { } + + @Override + public byte[] getBytes() { + + IoBuffer buffer = bufferPool.allocate(28, false).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(CRC.StringtoCRC(buffName)); + if(duration > 0) { + buffer.putInt((int) (totalPlayTime + getRemainingDuration())); + buffer.putInt(0); + buffer.putInt((int) duration); + } else { + buffer.putInt(-1); + buffer.putInt(0); + buffer.putInt(-1); + } + buffer.putLong(ownerId); + buffer.putInt(1); // unk + + buffer.flip(); + + return buffer.array(); + + } + + public float getDuration() { + return duration; + } + + public void setDuration(float duration) { + this.duration = duration; + } + + public String getBuffName() { + return buffName; + } + + public void setBuffName(String buffName) { + this.buffName = buffName; + } + + public long getOwnerId() { + return ownerId; + } + + public void setOwnerId(long ownerId) { + this.ownerId = ownerId; + } + + public String getEffect1Name() { + return effect1Name; + } + + public void setEffect1Name(String effect1Name) { + this.effect1Name = effect1Name; + } + + public String getEffect2Name() { + return effect2Name; + } + + public void setEffect2Name(String effect2Name) { + this.effect2Name = effect2Name; + } + + public String getEffect3Name() { + return effect3Name; + } + + public void setEffect3Name(String effect3Name) { + this.effect3Name = effect3Name; + } + + public String getEffect4Name() { + return effect4Name; + } + + public void setEffect4Name(String effect4Name) { + this.effect4Name = effect4Name; + } + + public String getEffect5Name() { + return effect5Name; + } + + public void setEffect5Name(String effect5Name) { + this.effect5Name = effect5Name; + } + + public float getEffect1Value() { + return effect1Value; + } + + public void setEffect1Value(float effect1Value) { + this.effect1Value = effect1Value; + } + + public float getEffect2Value() { + return effect2Value; + } + + public void setEffect2Value(float effect2Value) { + this.effect2Value = effect2Value; + } + + public float getEffect3Value() { + return effect3Value; + } + + public void setEffect3Value(float effect3Value) { + this.effect3Value = effect3Value; + } + + public float getEffect4Value() { + return effect4Value; + } + + public void setEffect4Value(float effect4Value) { + this.effect4Value = effect4Value; + } + + public float getEffect5Value() { + return effect5Value; + } + + public void setEffect5Value(float effect5Value) { + this.effect5Value = effect5Value; + } + + public String getParticleEffect() { + return particleEffect; + } + + public void setParticleEffect(String particleEffect) { + this.particleEffect = particleEffect; + } + + public boolean isDebuff() { + return isDebuff; + } + + public void setDebuff(boolean isDebuff) { + this.isDebuff = isDebuff; + } + + public boolean isRemoveOnDeath() { + return removeOnDeath; + } + + public void setRemoveOnDeath(boolean removeOnDeath) { + this.removeOnDeath = removeOnDeath; + } + + public boolean isRemovableByPlayer() { + return isRemovableByPlayer; + } + + public void setRemovableByPlayer(boolean isRemovableByPlayer) { + this.isRemovableByPlayer = isRemovableByPlayer; + } + + public int getMaxStacks() { + return maxStacks; + } + + public void setMaxStacks(int maxStacks) { + this.maxStacks = maxStacks; + } + + public boolean isPersistent() { + return isPersistent; + } + + public void setPersistent(boolean isPersistent) { + this.isPersistent = isPersistent; + } + + public boolean isRemoveOnRespec() { + return removeOnRespec; + } + + public void setRemoveOnRespec(boolean removeOnRespec) { + this.removeOnRespec = removeOnRespec; + } + + public boolean isAiRemoveOnEndCombat() { + return aiRemoveOnEndCombat; + } + + public void setAiRemoveOnEndCombat(boolean aiRemoveOnEndCombat) { + this.aiRemoveOnEndCombat = aiRemoveOnEndCombat; + } + + public boolean isDecayOnPvPDeath() { + return decayOnPvPDeath; + } + + public void setDecayOnPvPDeath(boolean decayOnPvPDeath) { + this.decayOnPvPDeath = decayOnPvPDeath; + } + + public void setStartTime() { + this.startTime = System.currentTimeMillis(); + } + + public int getRemainingDuration() { + + long currentTime = System.currentTimeMillis(); + long timeDiff = (currentTime - startTime) / 1000; + int remaining = (int) (duration - timeDiff); + System.out.println("Buff remaining: " + remaining); + return remaining; + + } + + public int getTotalPlayTime() { + return totalPlayTime; + } + + public void setTotalPlayTime(int totalPlayTime) { + this.totalPlayTime = totalPlayTime; + } + +} diff --git a/src/resources/objects/IListObject.java b/src/resources/objects/IListObject.java index 0af809cf..12b36650 100644 --- a/src/resources/objects/IListObject.java +++ b/src/resources/objects/IListObject.java @@ -21,6 +21,9 @@ ******************************************************************************/ package resources.objects; +import com.sleepycat.persist.model.Persistent; + +@Persistent public interface IListObject { public byte[] getBytes(); diff --git a/src/resources/objects/ListObject.java b/src/resources/objects/ListObject.java index 69a4caf6..efea9b1e 100644 --- a/src/resources/objects/ListObject.java +++ b/src/resources/objects/ListObject.java @@ -25,10 +25,14 @@ import java.nio.ByteBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; + import resources.common.StringUtilities; + public abstract class ListObject implements IListObject { + public ListObject() { } + protected final Object objectMutex = new Object(); public SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); diff --git a/src/resources/objects/ObjectMessageBuilder.java b/src/resources/objects/ObjectMessageBuilder.java index e8814ea5..d39f558d 100644 --- a/src/resources/objects/ObjectMessageBuilder.java +++ b/src/resources/objects/ObjectMessageBuilder.java @@ -28,15 +28,21 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; +import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; + import resources.common.Opcodes; import engine.resources.objects.SWGObject; +@Persistent public abstract class ObjectMessageBuilder { - public SWGObject object; - public SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); + public SWGObject object; + @NotPersistent + public SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); + public IoBuffer createBaseline(String objectType, byte viewType, IoBuffer data, int size) { IoBuffer buffer = bufferPool.allocate(23 + size, false).order(ByteOrder.LITTLE_ENDIAN); diff --git a/src/resources/objects/SWGList.java b/src/resources/objects/SWGList.java index f33d38be..57a09ae2 100644 --- a/src/resources/objects/SWGList.java +++ b/src/resources/objects/SWGList.java @@ -31,41 +31,39 @@ import java.util.ListIterator; import org.apache.mina.core.buffer.IoBuffer; import com.sleepycat.persist.model.NotPersistent; +import com.sleepycat.persist.model.Persistent; /* A SWGList element MUST implement IListObject, or it will refuse to work with it */ - +@Persistent public class SWGList implements List { private List list = new ArrayList(); @NotPersistent - private int updateCounter; - + private int updateCounter = 1; private ObjectMessageBuilder messageBuilder; private byte viewType; private short updateType; - + @NotPersistent protected final Object objectMutex = new Object(); + public SWGList() { } + public SWGList(ObjectMessageBuilder messageBuilder, int viewType, int updateType) { this.messageBuilder = messageBuilder; this.viewType = (byte) viewType; this.updateType = (short) updateType; } - + @Override public boolean add(E e) { - synchronized(objectMutex) { - if (e instanceof IListObject) { - if (list.add(e)) { - queue(item(1, list.lastIndexOf(e), ((IListObject) e).getBytes(), true, true)); - - return true; - } - } - + synchronized(objectMutex) { + if (list.add(e) && e instanceof IListObject) { + queue(item(1, list.lastIndexOf(e), ((IListObject) e).getBytes(), true, true)); + return true; + } return false; } } - + @Override public void add(int index, E element) { synchronized(objectMutex) { if (element instanceof IListObject) { @@ -74,7 +72,7 @@ public class SWGList implements List { } } } - + @Override public boolean addAll(Collection c) { synchronized(objectMutex) { if (!c.isEmpty()) { @@ -102,7 +100,7 @@ public class SWGList implements List { return false; } } - + @Override public boolean addAll(int index, Collection c) { synchronized(objectMutex) { if (!c.isEmpty()) { @@ -126,74 +124,71 @@ public class SWGList implements List { return false; } } - + @Override public void clear() { synchronized(objectMutex) { list.clear(); queue(item(4, 0, null, false, false)); } } - + @Override public boolean contains(Object o) { synchronized(objectMutex) { return list.contains(o); } } - + @Override public boolean containsAll(Collection c) { synchronized(objectMutex) { return list.containsAll(c); } } - + @Override public E get(int index) { synchronized(objectMutex) { return list.get(index); } } - public List get() { - synchronized(objectMutex) { - return list; - } + return list; } - + @Override public int indexOf(Object o) { synchronized(objectMutex) { return list.indexOf(o); } } - + @Override public boolean isEmpty() { synchronized(objectMutex) { return list.isEmpty(); } } - + @Override public Iterator iterator() { synchronized(objectMutex) { return list.iterator(); } } - + @Override public int lastIndexOf(Object o) { synchronized(objectMutex) { return list.lastIndexOf(o); } } - + @Override public ListIterator listIterator() { synchronized(objectMutex) { return list.listIterator(); } } - + @Override public ListIterator listIterator(int index) { synchronized(objectMutex) { return listIterator(index); } } - + @Override public boolean remove(Object o) { synchronized(objectMutex) { int index = list.indexOf(o); @@ -206,7 +201,7 @@ public class SWGList implements List { } } } - + @Override public E remove(int index) { synchronized(objectMutex) { E element = list.remove(index); @@ -216,7 +211,7 @@ public class SWGList implements List { return (E) element; } } - + @Override public boolean removeAll(Collection c) { synchronized(objectMutex) { if (!c.isEmpty()) { @@ -243,13 +238,13 @@ public class SWGList implements List { return false; } } - + @Override public boolean retainAll(Collection c) { synchronized(objectMutex) { return list.retainAll(c); } } - + @Override public E set(int index, E element) { synchronized(objectMutex) { if (element instanceof IListObject) { @@ -291,25 +286,25 @@ public class SWGList implements List { return false; } } - + @Override public int size() { synchronized(objectMutex) { return list.size(); } } - + @Override public List subList(int fromIndex, int toIndex) { synchronized(objectMutex) { return list.subList(fromIndex, toIndex); } } - + @Override public Object[] toArray() { synchronized(objectMutex) { return list.toArray(); } } - + @Override public T[] toArray(T[] a) { synchronized(objectMutex) { return list.toArray(a); @@ -355,5 +350,7 @@ public class SWGList implements List { messageBuilder.sendListDelta(viewType, updateType, buffer); } + + public Object getMutex() { return objectMutex; } } diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index 1c8f7080..2fc7b875 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -23,18 +23,25 @@ package resources.objects.creature; import java.nio.ByteOrder; + import org.apache.mina.core.buffer.IoBuffer; +import com.sleepycat.persist.model.Persistent; + import engine.resources.common.CRC; +import resources.objects.Buff; import resources.objects.ObjectMessageBuilder; import engine.resources.objects.SWGObject; import engine.resources.objects.SkillMod; +import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; +@Persistent public class CreatureMessageBuilder extends ObjectMessageBuilder { + public CreatureMessageBuilder() { } public CreatureMessageBuilder(CreatureObject creatureObject) { @@ -59,7 +66,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { } else { buffer.putInt(creature.getSkills().size()); buffer.putInt(creature.getSkillsUpdateCounter()); - for(String skill : creature.getSkills()) + for(String skill : creature.getSkills().get()) buffer.put(getAsciiString(skill)); } int size = buffer.position(); @@ -74,7 +81,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { public IoBuffer buildBaseline3() { CreatureObject creature = (CreatureObject) object; - IoBuffer buffer = bufferPool.allocate(300, false).order(ByteOrder.LITTLE_ENDIAN); + IoBuffer buffer = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); buffer.setAutoExpand(true); buffer.putShort((short) 19); // Object Count @@ -94,7 +101,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(creature.getFactionStatus()); - byte[] customizationData = creature.getCustomizationData(); + byte[] customizationData = creature.getCustomization(); if(customizationData.length <= 0) buffer.putShort((short) 0); @@ -115,8 +122,11 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.put((byte) 1); buffer.putLong(creature.getOwnerId()); - - buffer.putFloat(creature.getHeight()); + + float height = creature.getHeight(); + if (height < 0.7 || height > 1.5) + height = 1; + buffer.putFloat(height); buffer.putInt(0); // battle fatigue buffer.putLong(creature.getStateBitmask()); int size = buffer.position(); @@ -147,7 +157,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(creature.getSkillMods().size()); buffer.putInt(creature.getSkillModsUpdateCounter()); - for(SkillMod skillMod : creature.getSkillMods()) { + for(SkillMod skillMod : creature.getSkillMods().get()) { buffer.put((byte) 0); buffer.put(getAsciiString(skillMod.getSkillModString())); buffer.putInt(skillMod.getBase()); @@ -177,7 +187,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(creature.getAbilities().size()); buffer.putInt(creature.getAbilitiesUpdateCounter()); - for(String ability : creature.getAbilities()) { + for(String ability : creature.getAbilities().get()) { buffer.put((byte) 0); buffer.put(getAsciiString(ability)); buffer.putInt(1); @@ -247,11 +257,11 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(6); // Current HAM - buffer.putInt(0); + buffer.putInt(creature.getHamListCounter()); - buffer.putInt(20000); + buffer.putInt(creature.getHealth()); buffer.putInt(0); - buffer.putInt(12500); + buffer.putInt(creature.getAction()); buffer.putInt(0); buffer.putInt(0x2C01); buffer.putInt(0); @@ -265,6 +275,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(0x2C01); buffer.putInt(0); + if(creature.getEquipmentList().isEmpty()) { buffer.putInt(0); @@ -273,7 +284,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(creature.getEquipmentList().size()); buffer.putInt(0); - for(SWGObject obj : creature.getEquipmentList()) { + for(SWGObject obj : creature.getEquipmentList().get()) { if(obj instanceof TangibleObject) { TangibleObject tangible = (TangibleObject) obj; @@ -312,9 +323,47 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putShort((short) 0); buffer.put((byte) 1); - buffer.putInt(0); // Buff List todo later - buffer.putInt(0); - + if(creature.getBuffList().isEmpty()) { + buffer.putInt(0); + buffer.putInt(creature.getBuffListCounter()); + } else { + buffer.putInt(creature.getBuffList().size() + 1); + buffer.putInt(creature.getBuffListCounter()); + + buffer.put((byte) 0); + //buffer.putInt(0x2098793D); + buffer.putInt(0); + buffer.putInt(-1); + buffer.putInt(0); + buffer.putInt(0); + buffer.putLong(creature.getObjectID()); + + PlayerObject player = (PlayerObject) creature.getSlottedObject("ghost"); + + for(Buff buff : creature.getBuffList().get()) { + + buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + buffer.put((byte) 1); + buffer.putInt(0); + buffer.putInt(CRC.StringtoCRC(buff.getBuffName())); + if(buff.getDuration() > 0) { + buffer.putInt((int) (buff.getTotalPlayTime() + buff.getRemainingDuration())); + buffer.putInt(0); + buffer.putInt((int) buff.getDuration()); + } else { + buffer.putInt(-1); + buffer.putInt(0); + buffer.putInt(0); + } + + buffer.putLong(creature.getObjectID()); + + } + + buffer.putInt(1); + + } + buffer.putShort((short) 0); buffer.putInt(0xFFFFFFFF); buffer.put((byte) 1); @@ -327,7 +376,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(creature.getAppearanceEquipmentList().size()); buffer.putInt(0); - for(SWGObject obj : creature.getAppearanceEquipmentList()) { + for(SWGObject obj : creature.getAppearanceEquipmentList().get()) { if(obj instanceof TangibleObject) { TangibleObject tangible = (TangibleObject) obj; @@ -350,19 +399,6 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(0); - //buffer.put((byte) 0); - - - - /*buffer.putShort((short) 1); - buffer.putInt(0); - buffer.putInt(0xFFFFFFFF); - buffer.putInt(1); - buffer.putInt(0); - buffer.putInt(0); - buffer.putInt(0); - buffer.putShort((short) 0); - buffer.put((byte)0);*/ int size = buffer.position(); buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); @@ -594,6 +630,116 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { } + public IoBuffer buildHealthDelta(int health) { + + CreatureObject creature = (CreatureObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getHamListCounter()); + buffer.put((byte) 2); + buffer.putShort((short) 0); + buffer.putInt(health); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x15, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildActionDelta(int action) { + + CreatureObject creature = (CreatureObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getHamListCounter()); + buffer.put((byte) 2); + buffer.putShort((short) 2); + buffer.putInt(action); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x15, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildMaxHealthDelta(int health) { + + CreatureObject creature = (CreatureObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getHamListCounter()); + buffer.put((byte) 2); + buffer.putShort((short) 0); + buffer.putInt(health); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x16, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildMaxActionDelta(int action) { + + CreatureObject creature = (CreatureObject) object; + + IoBuffer buffer = bufferPool.allocate(15, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getHamListCounter()); + buffer.put((byte) 2); + buffer.putShort((short) 2); + buffer.putInt(action); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x16, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildAddBuffDelta(Buff buff) { + + CreatureObject creature = (CreatureObject) object; + PlayerObject player = (PlayerObject) creature.getSlottedObject("ghost"); + + IoBuffer buffer = bufferPool.allocate(37, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getBuffListCounter()); + buff.setTotalPlayTime((int) (player.getTotalPlayTime() + (System.currentTimeMillis() - player.getLastPlayTimeUpdate()) / 1000)); + buffer.put((byte) 0); + buffer.put(buff.getBytes()); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x1A, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildRemoveBuffDelta(Buff buff) { + + CreatureObject creature = (CreatureObject) object; + + IoBuffer buffer = bufferPool.allocate(37, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(1); + buffer.putInt(creature.getBuffListCounter()); + buffer.put((byte) 1); + buffer.put(buff.getBytes()); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("CREO", (byte) 6, (short) 1, (short) 0x1A, buffer, size + 4); + + return buffer; + + } + + + @Override public void sendListDelta(byte viewType, short updateType, IoBuffer data) { // TODO Auto-generated method stub diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 479d2e76..52df5b26 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -41,7 +41,8 @@ import com.sleepycat.persist.model.Entity; import com.sleepycat.persist.model.NotPersistent; import engine.clients.Client; -import engine.resources.objects.Buff; +import resources.objects.Buff; +import resources.objects.SWGList; import engine.resources.objects.IPersistent; import engine.resources.objects.MissionCriticalObject; import engine.resources.objects.SWGObject; @@ -54,7 +55,7 @@ import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; @Entity -public class CreatureObject extends SWGObject implements IPersistent { +public class CreatureObject extends TangibleObject implements IPersistent { @NotPersistent private Transaction txn; @@ -62,16 +63,12 @@ public class CreatureObject extends SWGObject implements IPersistent { // CREO 1 private int bankCredits = 0; private int cashCredits = 0; - private List skills = new ArrayList(); + private SWGList skills; @NotPersistent private int skillsUpdateCounter = 0; // CREO 3 - private byte[] customizationData; - private int optionBitmask = 0; - private int incapTimer = 10; private byte posture = 0; - private String faction; private int factionStatus = 0; private float height; private int battleFatigue = 0; @@ -81,7 +78,7 @@ public class CreatureObject extends SWGObject implements IPersistent { // CREO 4 private float accelerationMultiplierBase = 1; private float accelerationMultiplierMod = 1; - private List skillMods = new ArrayList(); + private SWGList skillMods; @NotPersistent private int skillModsUpdateCounter = 0; private float speedMultiplierBase = 1; @@ -93,17 +90,15 @@ public class CreatureObject extends SWGObject implements IPersistent { private float turnRadius = 1; private float walkSpeed = (float) 2.75; private float waterModPercent = 1; - private List abilities = new ArrayList(); + private SWGList abilities; private int abilitiesUpdateCounter = 0; - private List missionCriticalObjects = new ArrayList(); + private SWGList missionCriticalObjects; @NotPersistent private int missionCriticalObjectsUpdateCounter = 0; // CREO6 - @NotPersistent - private List defendersList = new ArrayList(); // unused in packets but useful for the server private byte combatFlag = 0; private short level = 0; private String currentAnimation; @@ -118,13 +113,22 @@ public class CreatureObject extends SWGObject implements IPersistent { private byte moodId = 0; private int performanceCounter = 0; private int performanceId = 0; - private List equipmentList = new ArrayList(); + private int health = 20000; + private int action = 12500; + @NotPersistent + private int HAMListCounter = 0; + private int maxHealth = 20000; + private int maxAction = 12500; + @NotPersistent + private int maxHAMListCounter = 0; + + private SWGList equipmentList; @NotPersistent private int equipmentListUpdateCounter = 0; - private List buffList = new ArrayList(); + private SWGList buffList = new SWGList(); @NotPersistent private int buffListUpdateCounter = 0; - private List appearanceEquipmentList = new ArrayList(); + private SWGList appearanceEquipmentList; @NotPersistent private int appearanceEquipmentListUpdateCounter = 0; @@ -136,8 +140,15 @@ public class CreatureObject extends SWGObject implements IPersistent { public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { - super(objectID, planet, position, orientation, Template); + super(objectID, planet, Template, position, orientation); messageBuilder = new CreatureMessageBuilder(this); + skills = new SWGList(messageBuilder, 1, 3); + skillMods = new SWGList(messageBuilder, 4, 3); + abilities = new SWGList(messageBuilder, 4, 14); + missionCriticalObjects = new SWGList(messageBuilder, 4, 13); + equipmentList = new SWGList(messageBuilder, 6, 0x17); + buffList = new SWGList(messageBuilder, 6, 0x1A); + appearanceEquipmentList = new SWGList(messageBuilder, 6, 0x1F); } public CreatureObject() { @@ -179,7 +190,7 @@ public class CreatureObject extends SWGObject implements IPersistent { } } - public List getSkills() { + public SWGList getSkills() { return skills; } @@ -195,27 +206,10 @@ public class CreatureObject extends SWGObject implements IPersistent { } } - public byte[] getCustomizationData() { + @Override + public void setOptionsBitmask(int optionBitmask) { synchronized(objectMutex) { - return customizationData; - } - } - - public void setCustomizationData(byte[] customizationData) { - synchronized(objectMutex) { - this.customizationData = customizationData; - } - } - - public int getOptionBitmask() { - synchronized(objectMutex) { - return optionBitmask; - } - } - - public void setOptionBitmask(int optionBitmask) { - synchronized(objectMutex) { - this.optionBitmask = optionBitmask; + this.optionsBitmask = optionBitmask; } IoBuffer optionDelta = messageBuilder.buildOptionMaskDelta(optionBitmask); @@ -224,18 +218,6 @@ public class CreatureObject extends SWGObject implements IPersistent { } - public int getIncapTimer() { - synchronized(objectMutex) { - return incapTimer; - } - } - - public void setIncapTimer(int incapTimer) { - synchronized(objectMutex) { - this.incapTimer = incapTimer; - } - } - public byte getPosture() { synchronized(objectMutex) { return posture; @@ -254,12 +236,7 @@ public class CreatureObject extends SWGObject implements IPersistent { notifyObservers(objController, true); } - public String getFaction() { - synchronized(objectMutex) { - return faction; - } - } - + @Override public void setFaction(String faction) { synchronized(objectMutex) { this.faction = faction; @@ -370,9 +347,27 @@ public class CreatureObject extends SWGObject implements IPersistent { } } - public List getSkillMods() { + public SWGList getSkillMods() { return skillMods; } + + public SkillMod getSkillMod(String name) { + synchronized(skillMods.getMutex()) { + for(SkillMod skillMod : skillMods.get()) { + if(skillMod.getSkillModString().equals(name)) + return skillMod; + } + } + return null; + } + + public void addSkillMod(String name, int base) { + SkillMod skillMod = new SkillMod(); + skillMod.setBase(base); + skillMod.setSkillModString(name); + skillMod.setModifier(0); + skillMods.add(skillMod); + } public short getSkillModsUpdateCounter() { synchronized(objectMutex) { @@ -503,7 +498,7 @@ public class CreatureObject extends SWGObject implements IPersistent { } } - public List getAbilities() { + public SWGList getAbilities() { return abilities; } @@ -518,13 +513,13 @@ public class CreatureObject extends SWGObject implements IPersistent { this.abilitiesUpdateCounter = abilitiesUpdateCounter; } } - - public List getMissionCriticalObjects() { - return missionCriticalObjects; + + public void addAbility(String abilityName) { + abilities.add(abilityName); } - public List getDefendersList() { - return defendersList; + public SWGList getMissionCriticalObjects() { + return missionCriticalObjects; } public byte getCombatFlag() { @@ -537,6 +532,9 @@ public class CreatureObject extends SWGObject implements IPersistent { synchronized(objectMutex) { this.combatFlag = combatFlag; } + IoBuffer combatDelta = messageBuilder.buildCombatFlagDelta(combatFlag); + + notifyObservers(combatDelta, true); } public short getLevel() { @@ -714,15 +712,15 @@ public class CreatureObject extends SWGObject implements IPersistent { } } - public List getEquipmentList() { + public SWGList getEquipmentList() { return equipmentList; } - public List getBuffList() { + public SWGList getBuffList() { return buffList; } - public List getAppearanceEquipmentList() { + public SWGList getAppearanceEquipmentList() { return appearanceEquipmentList; } @@ -738,17 +736,13 @@ public class CreatureObject extends SWGObject implements IPersistent { public void addObjectToEquipList(SWGObject object) { if(object instanceof TangibleObject || object instanceof WeaponObject) { - synchronized(objectMutex) { - equipmentList.add(object); - } + equipmentList.add(object); } } public void removeObjectFromEquipList(SWGObject object) { if(object instanceof TangibleObject || object instanceof WeaponObject) { - synchronized(objectMutex) { - equipmentList.remove(object); - } + equipmentList.remove(object); } } @@ -767,17 +761,42 @@ public class CreatureObject extends SWGObject implements IPersistent { destination.getSession().write(messageBuilder.buildBaseline1()); destination.getSession().write(messageBuilder.buildBaseline4()); } - destination.getSession().write(messageBuilder.buildBaseline8()); - destination.getSession().write(messageBuilder.buildBaseline9()); - + //destination.getSession().write(messageBuilder.buildBaseline8()); + //destination.getSession().write(messageBuilder.buildBaseline9()); + UpdatePostureMessage upm = new UpdatePostureMessage(getObjectID(), (byte) 0); - destination.getSession().write(upm.serialize()); - if(destination != getClient()) { - UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID(), 55); - destination.getSession().write(upvpm.serialize()); - } + //destination.getSession().write(upm.serialize()); - + if(destination != getClient()) { + UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); + if (factionStatus == 1 && faction == "imperial") { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Imperial); + upvpm.setStatus(16); + } + + if (factionStatus == 1 && faction == "rebel") { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Rebel); + upvpm.setStatus(16); + } + + if (factionStatus == 2 && faction == "imperial") { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Imperial); + upvpm.setStatus(55); + } + if (factionStatus == 2 && faction == "rebel") { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Rebel); + upvpm.setStatus(55); + } + if(factionStatus == 0 && faction == "neutral") { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Neutral); + upvpm.setStatus(16); + } + else { + upvpm.setFaction(UpdatePVPStatusMessage.factionCRC.Neutral); + upvpm.setStatus(16); + } + //destination.getSession().write(upvpm.serialize()); + } } public void sendSystemMessage(String message, byte displayType) { @@ -789,4 +808,133 @@ public class CreatureObject extends SWGObject implements IPersistent { } + public int getHealth() { + synchronized(objectMutex) { + return health; + } + } + + public void setHealth(int health) { + IoBuffer delta; + synchronized(objectMutex) { + if(health > maxHealth) + health = maxHealth; + this.health = health; + setHamListCounter(getHamListCounter() + 1); + delta = messageBuilder.buildHealthDelta(health); + } + notifyObservers(delta, true); + } + + public int getAction() { + synchronized(objectMutex) { + return action; + } + } + + public void setAction(int action) { + IoBuffer delta; + synchronized(objectMutex) { + if(action > maxAction) + action = maxAction; + this.action = action; + setHamListCounter(getHamListCounter() + 1); + delta = messageBuilder.buildActionDelta(action); + } + notifyObservers(delta, true); + } + + public int getHamListCounter() { + synchronized(objectMutex) { + return HAMListCounter; + } + } + + public void setHamListCounter(int hamListCounter) { + synchronized(objectMutex) { + this.HAMListCounter = hamListCounter; + } + } + + public int getMaxHealth() { + synchronized(objectMutex) { + return maxHealth; + } + } + + public void setMaxHealth(int maxHealth) { + synchronized(objectMutex) { + this.maxHealth = maxHealth; + setMaxHAMListCounter(getMaxHAMListCounter() + 1); + } + notifyObservers(messageBuilder.buildMaxHealthDelta(maxHealth), true); + } + + public int getMaxAction() { + synchronized(objectMutex) { + return maxAction; + } + } + + public void setMaxAction(int maxAction) { + synchronized(objectMutex) { + this.maxAction = maxAction; + setMaxHAMListCounter(getMaxHAMListCounter() + 1); + } + notifyObservers(messageBuilder.buildMaxActionDelta(maxAction), true); + } + + public int getMaxHAMListCounter() { + synchronized(objectMutex) { + return maxHAMListCounter; + } + } + + public void setMaxHAMListCounter(int maxHAMListCounter) { + synchronized(objectMutex) { + this.maxHAMListCounter = maxHAMListCounter; + } + } + + public void addBuff(Buff buff) { + synchronized(objectMutex) { + buffList.get().add(buff); + setBuffListCounter(getBuffListCounter() + 1); + + } + buff.setStartTime(); + notifyObservers(messageBuilder.buildAddBuffDelta(buff), true); + } + + public void removeBuff(Buff buff) { + synchronized(objectMutex) { + buffList.get().remove(buff); + setBuffListCounter(getBuffListCounter() + 1); + } + notifyObservers(messageBuilder.buildRemoveBuffDelta(buff), true); + } + + public int getBuffListCounter() { + synchronized(objectMutex) { + return buffListUpdateCounter; + } + } + + public void setBuffListCounter(int buffListCounter) { + synchronized(objectMutex) { + this.buffListUpdateCounter = buffListCounter; + } + } + + public Buff getBuffByName(String buffName) { + synchronized(objectMutex) { + for(Buff buff : buffList.get()) { + if(buff.getBuffName().equals(buffName)) + return buff; + } + } + return null; + } + + } diff --git a/src/resources/objects/player/PlayerMessageBuilder.java b/src/resources/objects/player/PlayerMessageBuilder.java index 3304d76f..33f6db6e 100644 --- a/src/resources/objects/player/PlayerMessageBuilder.java +++ b/src/resources/objects/player/PlayerMessageBuilder.java @@ -80,7 +80,7 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); // born date? - buffer.putInt(0); // total play time? + buffer.putInt(player.getTotalPlayTime()); // total play time? buffer.putInt(getProfData(player.getProfession())); // prof icon @@ -172,6 +172,7 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { int size = buffer.position(); + buffer = bufferPool.allocate(size, false).put(buffer.array(), 0, size); buffer.flip(); @@ -375,6 +376,138 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { } + public IoBuffer buildWaypointAddDelta(WaypointObject waypoint) { + + PlayerObject player = (PlayerObject) object; + IoBuffer buffer = bufferPool.allocate(59 + waypoint.getName().length() * 2, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.setAutoExpand(true); + + int nextCounter = player.getWaypointListUpdateCounter() + 1; + player.setWaypointListUpdateCounter(nextCounter); + buffer.putInt(1); + buffer.putInt(player.getWaypointListUpdateCounter()); + + buffer.put((byte) 0); // updateType (SubType) + + buffer.putLong(waypoint.getObjectID()); + buffer.putInt(waypoint.getCellId()); + + buffer.putFloat(waypoint.getPosition().x); + buffer.putFloat(waypoint.getPosition().y); + buffer.putFloat(waypoint.getPosition().z); + + buffer.putLong(0); // networklocationId + buffer.putInt(waypoint.getPlanetCRC()); + + buffer.put(getUnicodeString(waypoint.getName())); + buffer.putLong(waypoint.getObjectID()); + + buffer.put((byte) waypoint.getColor()); + + if (waypoint.isActive()) { buffer.put((byte) 1); } + else { buffer.put((byte) 0); } + + int size = buffer.position(); + buffer.flip(); + + buffer = createDelta("PLAY", (byte) 8, (short) 1, (short) 1, buffer, size + 4); + //System.out.println("WaypointAdd: " + buffer.getHexDump()); + return buffer; + + } + + public IoBuffer buildWaypointRemoveDelta(WaypointObject waypoint) { + + IoBuffer buffer = bufferPool.allocate(59 + waypoint.getName().length() * 2, false).order(ByteOrder.LITTLE_ENDIAN); + PlayerObject player = (PlayerObject) object; + + int nextCounter = player.getWaypointListUpdateCounter() + 1; + player.setWaypointListUpdateCounter(nextCounter); + + buffer.putInt(1); + buffer.putInt(player.getWaypointListUpdateCounter()); + + buffer.put((byte) 1); // updateType (SubType) + + buffer.putLong(waypoint.getObjectID()); + buffer.putInt(waypoint.getCellId()); + + buffer.putFloat(waypoint.getPosition().x); + buffer.putFloat(waypoint.getPosition().y); + buffer.putFloat(waypoint.getPosition().z); + + buffer.putLong(0); // networklocationId + buffer.putInt(waypoint.getPlanetCRC()); + + buffer.put(getUnicodeString(waypoint.getName())); + buffer.putLong(waypoint.getObjectID()); + + buffer.put((byte) waypoint.getColor()); + + if (waypoint.isActive()) { buffer.put((byte) 1); } + else { buffer.put((byte) 0); } + + int size = buffer.position(); + buffer.flip(); + + buffer = createDelta("PLAY", (byte) 8, (short) 1, (short) 1, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildWaypointUpdateDelta(WaypointObject waypoint) { + + IoBuffer buffer = bufferPool.allocate(59 + waypoint.getName().length() * 2, false).order(ByteOrder.LITTLE_ENDIAN); + PlayerObject player = (PlayerObject) object; + + int nextCounter = player.getWaypointListUpdateCounter() + 1; + player.setWaypointListUpdateCounter(nextCounter); + + buffer.putInt(1); + buffer.putInt(player.getWaypointListUpdateCounter()); + + buffer.put((byte) 2); // updateType (SubType) + + buffer.putLong(waypoint.getObjectID()); + buffer.putInt(waypoint.getCellId()); + + buffer.putFloat(waypoint.getPosition().x); + buffer.putFloat(waypoint.getPosition().y); + buffer.putFloat(waypoint.getPosition().z); + + buffer.putLong(0); // networklocationId << cluster system I guess? + buffer.putInt(waypoint.getPlanetCRC()); + + buffer.put(getUnicodeString(waypoint.getName())); + buffer.putLong(waypoint.getObjectID()); + + buffer.put((byte) waypoint.getColor()); + + if (waypoint.isActive()) { buffer.put((byte) 1); } + else { buffer.put((byte) 0); } // isActive. Activates automatically when created. + + int size = buffer.position(); + buffer.flip(); + + buffer = createDelta("PLAY", (byte) 8, (short) 1, (short) 1, buffer, size + 4); + + return buffer; + + } + + public IoBuffer buildTotalPlayTimeDelta(int totalPlayTime) { + + IoBuffer buffer = bufferPool.allocate(4, false).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(totalPlayTime); + int size = buffer.position(); + buffer.flip(); + buffer = createDelta("PLAY", (byte) 3, (short) 1, (short) 0x09, buffer, size + 4); + + return buffer; + + } + public int getProfData(String profession) { switch (profession) { diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 4472829c..00d644fb 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -112,6 +112,9 @@ public class PlayerObject extends SWGObject { @NotPersistent private PlayerMessageBuilder messageBuilder; + @NotPersistent + private long lastPlayTimeUpdate = System.currentTimeMillis(); + public PlayerObject() { @@ -120,7 +123,7 @@ public class PlayerObject extends SWGObject { } public PlayerObject(long objectID, Planet planet) { - super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0), "object/player/shared_player.iff"); + super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 0, 0), "object/player/shared_player.iff"); messageBuilder = new PlayerMessageBuilder(this); } @@ -180,6 +183,7 @@ public class PlayerObject extends SWGObject { synchronized(objectMutex) { this.totalPlayTime = totalPlayTime; } + getContainer().notifyObservers(messageBuilder.buildTotalPlayTimeDelta(totalPlayTime), true); } public String getHome() { @@ -202,6 +206,46 @@ public class PlayerObject extends SWGObject { return waypoints; } + public int getWaypointListUpdateCounter() { + synchronized(objectMutex) { + return waypointListUpdateCounter; + } + } + + public void setWaypointListUpdateCounter(int count) { + synchronized(objectMutex){ + this.waypointListUpdateCounter = count; + } + } + + public void waypointUpdate(WaypointObject waypoint) { + synchronized(objectMutex) { + getContainer().getClient().getSession().write(messageBuilder.buildWaypointUpdateDelta(waypoint)); + } + } + + public void waypointRemove(WaypointObject waypoint) { + synchronized(objectMutex) { + getContainer().getClient().getSession().write(messageBuilder.buildWaypointRemoveDelta(waypoint)); + } + } + + public void waypointAdd(WaypointObject waypoint) { + synchronized(objectMutex) { + getContainer().getClient().getSession().write(messageBuilder.buildWaypointAddDelta(waypoint)); + } + } + + public WaypointObject getWaypointFromList(WaypointObject waypoint) { + synchronized(objectMutex) { + for(WaypointObject wp : waypoints) { + if(wp.getObjectID() == waypoint.getObjectID()) + return wp; + } + } + return null; + } + public int getCurrentForcePower() { synchronized(objectMutex) { return currentForcePower; @@ -449,14 +493,26 @@ public class PlayerObject extends SWGObject { if(destination == null || destination.getSession() == null) return; - if(destination.getParent().getObjectID() == getParentId()) { // only send to self + //if(destination.getParent().getObjectID() == getParentId()) { // only send to self destination.getSession().write(messageBuilder.buildBaseline3()); destination.getSession().write(messageBuilder.buildBaseline6()); destination.getSession().write(messageBuilder.buildBaseline8()); destination.getSession().write(messageBuilder.buildBaseline9()); - } + //} } + + public long getLastPlayTimeUpdate() { + synchronized(objectMutex) { + return lastPlayTimeUpdate; + } + } + + public void setLastPlayTimeUpdate(long lastPlayTimeUpdate) { + synchronized(objectMutex) { + this.lastPlayTimeUpdate = lastPlayTimeUpdate; + } + } } diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 7cce2933..e8c231e7 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -23,6 +23,11 @@ package resources.objects.tangible; import java.util.ArrayList; import java.util.List; +import java.util.Vector; + +import org.apache.mina.core.buffer.IoBuffer; + +import resources.objects.creature.CreatureObject; import com.sleepycat.persist.model.NotPersistent; @@ -41,14 +46,17 @@ public class TangibleObject extends SWGObject { // TODO: Thread safety - private int incapTimer = 10; + protected int incapTimer = 10; private int conditionDamage = 0; - - private byte[] customization; + protected int pvpBitmask = 0; + protected byte[] customization; private List componentCustomizations = new ArrayList(); - private int optionsBitmask = 0; + protected int optionsBitmask = 0; private int maxDamage = 0; private boolean staticObject = false; + protected String faction = ""; + @NotPersistent + private Vector defendersList = new Vector(); // unused in packets but useful for the server @NotPersistent private TangibleMessageBuilder messageBuilder; @@ -122,6 +130,100 @@ public class TangibleObject extends SWGObject { public void setStaticObject(boolean staticObject) { this.staticObject = staticObject; } + + public int getPvPBitmask() { + synchronized(objectMutex) { + return optionsBitmask; + } + } + + public void setPvPBitmask(int pvpBitmask) { + synchronized(objectMutex) { + this.pvpBitmask = pvpBitmask; + } + } + + public String getFaction() { + synchronized(objectMutex) { + return faction; + } + } + + public void setFaction(String faction) { + synchronized(objectMutex) { + this.faction = faction; + } + } + + public Vector getDefendersList() { + return defendersList; + } + + public void addDefender(TangibleObject defender) { + + defendersList.add(defender); + + if(this instanceof CreatureObject) { + CreatureObject creature = (CreatureObject) this; + + if(creature.getCombatFlag() == 0) + creature.setCombatFlag((byte) 1); + } + + } + + public void removeDefender(TangibleObject defender) { + + defendersList.remove(defender); + + if(this instanceof CreatureObject) { + CreatureObject creature = (CreatureObject) this; + + if(creature.getCombatFlag() == 1 && defendersList.isEmpty()) + creature.setCombatFlag((byte) 0); + } + + } + + public boolean isAttackableBy(CreatureObject attacker) { + + CreatureObject creature; + + if(this instanceof CreatureObject) { + creature = (CreatureObject) this; + if(creature.getDuelList().contains(attacker) && attacker.getDuelList().contains(this)) + return true; + } + + if(faction.equals("rebel") && attacker.getFaction().equals("rebel")) + return false; + else if(faction.equals("imperial") && attacker.getFaction().equals("imperial")) + return false; + else if(attacker.getSlottedObject("ghost") != null) { + + if(this instanceof CreatureObject && getSlottedObject("ghost") != null) { + + creature = (CreatureObject) this; + + if(creature.getFactionStatus() == 2 && attacker.getFactionStatus() == 2) + return true; + else + return false; + + } + + if((faction.equals("rebel") || faction.equals("imperial")) && attacker.getFactionStatus() >= 1) + return true; + else if((faction.equals("rebel") || faction.equals("imperial")) && attacker.getFactionStatus() == 0) + return false; + + return getPvPBitmask() == 1 || getPvPBitmask() == 2; + + } + + return getPvPBitmask() == 1 || getPvPBitmask() == 2; + } + @Override public void sendBaselines(Client destination) { diff --git a/src/resources/objects/waypoint/WaypointObject.java b/src/resources/objects/waypoint/WaypointObject.java index 655c6a71..9b027381 100644 --- a/src/resources/objects/waypoint/WaypointObject.java +++ b/src/resources/objects/waypoint/WaypointObject.java @@ -21,8 +21,6 @@ ******************************************************************************/ package resources.objects.waypoint; - - import com.sleepycat.persist.model.Persistent; import engine.clients.Client; diff --git a/src/resources/objects/weapon/WeaponMessageBuilder.java b/src/resources/objects/weapon/WeaponMessageBuilder.java index 25d5aa18..cca05d8b 100644 --- a/src/resources/objects/weapon/WeaponMessageBuilder.java +++ b/src/resources/objects/weapon/WeaponMessageBuilder.java @@ -66,9 +66,8 @@ public class WeaponMessageBuilder extends ObjectMessageBuilder { buffer.putFloat(weapon.getAttackSpeed()); buffer.putInt(0); buffer.putInt(0); - buffer.putShort((short) 0); - buffer.putInt(0x014280); // range 64m no idea how this converts to 64 - buffer.putShort((short) 0); + buffer.putFloat(weapon.getMaxRange()); + buffer.putInt(0); buffer.putInt(0); buffer.putInt(0); // those 2 ints have something to do with particle color diff --git a/src/resources/objects/weapon/WeaponObject.java b/src/resources/objects/weapon/WeaponObject.java index ed3a3c48..90319eac 100644 --- a/src/resources/objects/weapon/WeaponObject.java +++ b/src/resources/objects/weapon/WeaponObject.java @@ -50,23 +50,50 @@ public class WeaponObject extends SWGObject { private WeaponMessageBuilder messageBuilder; private float attackSpeed = 1; + private float maxRange; public WeaponObject(long objectID, Planet planet, String template) { super(objectID, planet, new Point3D(0, 0, 0), new Quaternion(1, 0, 1, 0), template); messageBuilder = new WeaponMessageBuilder(this); + calculateRange(); } + public WeaponObject(long objectID, Planet planet, String template, Point3D position, Quaternion orientation) { super(objectID, planet, position, orientation, template); messageBuilder = new WeaponMessageBuilder(this); + calculateRange(); } public WeaponObject() { super(); messageBuilder = new WeaponMessageBuilder(this); + //calculateRange(); } - + private void calculateRange() { + + int weaponType = getWeaponType(); + + switch(weaponType) { + + case 0: maxRange = 64; break; + case 1: maxRange = 50; break; + case 2: maxRange = 35; break; + case 3: maxRange = 64; break; + case 4: maxRange = 5; break; + case 5: maxRange = 5; break; + case 6: maxRange = 5; break; + case 7: maxRange = 5; break; + case 8: maxRange = 64; break; + case 9: maxRange = 5; break; + case 10: maxRange = 5; break; + case 11: maxRange = 5; break; + + } + + } + public int getIncapTimer() { return incapTimer; } @@ -129,6 +156,9 @@ public class WeaponObject extends SWGObject { String template = getTemplate(); + if(template == null) + return weaponType; + if(template.contains("rifle")) weaponType = 0; if(template.contains("carbine")) weaponType = 1; if(template.contains("pistol")) weaponType = 2; @@ -151,6 +181,7 @@ public class WeaponObject extends SWGObject { @Override public void sendBaselines(Client destination) { + if(destination == null || destination.getSession() == null) return; @@ -174,4 +205,34 @@ public class WeaponObject extends SWGObject { return messageBuilder; } + public float getMaxRange() { + return maxRange; + } + + public void setMaxRange(float maxRange) { + this.maxRange = maxRange; + } + + public boolean isMelee() { + + int weaponType = getWeaponType(); + + if(weaponType == 4 || weaponType == 5 || weaponType == 6 || weaponType == 7 || weaponType == 9 || weaponType == 10 || weaponType == 11) + return true; + + return false; + + } + + public boolean isRanged() { + + int weaponType = getWeaponType(); + + if(weaponType == 0 || weaponType == 1 || weaponType == 2 || weaponType == 3) + return true; + + return false; + + } + } diff --git a/src/services/AttributeService.java b/src/services/AttributeService.java index 60c4cffd..f5da7e71 100644 --- a/src/services/AttributeService.java +++ b/src/services/AttributeService.java @@ -47,9 +47,7 @@ public class AttributeService implements INetworkDispatch { } @Override - public void insertOpcodes(Map arg0, - Map arg1) { - // TODO Auto-generated method stub + public void insertOpcodes(Map arg0, Map arg1) { } diff --git a/src/services/BuffService.java b/src/services/BuffService.java new file mode 100644 index 00000000..aab4120d --- /dev/null +++ b/src/services/BuffService.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * 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.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + + +import resources.common.FileUtilities; +import resources.objects.Buff; +import resources.objects.creature.CreatureObject; +import resources.objects.player.PlayerObject; + +import main.NGECore; + +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class BuffService implements INetworkDispatch { + + private NGECore core; + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public BuffService(NGECore core) { + this.core = core; + } + + @Override + public void insertOpcodes(Map arg0, Map arg1) { + + } + + @Override + public void shutdown() { + + } + + public void addBuffToCreature(final CreatureObject creature, String buffName) { + + if(!FileUtilities.doesFileExist("scripts/buffs/" + buffName + ".py")) { + System.out.println("Buff script doesnt exist for: " + buffName); + return; + } + + final Buff buff = new Buff(buffName, creature.getObjectID()); + buff.setTotalPlayTime(((PlayerObject) creature.getSlottedObject("ghost")).getTotalPlayTime()); + if(creature.getBuffByName(buffName) != null) { + + Buff otherBuff = creature.getBuffByName(buffName); + if(otherBuff.getRemainingDuration() > buff.getDuration()) { + return; + } else { + removeBuffFromCreature(creature, otherBuff); + } + + } + + core.scriptService.callScript("scripts/buffs", "setup", buffName, core, creature, buff); + + creature.addBuff(buff); + scheduler.schedule(new Runnable() { + + @Override + public void run() { + + removeBuffFromCreature(creature, buff); + + } + + }, (long) buff.getDuration(), TimeUnit.SECONDS); + + } + + public void removeBuffFromCreature(CreatureObject creature, Buff buff) { + + if(!creature.getBuffList().contains(buff)) + return; + + core.scriptService.callScript("scripts/buffs", "removeBuff", buff.getBuffName(), core, creature, buff); + creature.removeBuff(buff); + + } + + public void clearBuffs(final CreatureObject creature) { + + // copy to array for thread safety + + for(final Buff buff : creature.getBuffList().get().toArray(new Buff[] { })) { + + if(buff.getRemainingDuration() > 0) { + scheduler.schedule(new Runnable() { + + @Override + public void run() { + + removeBuffFromCreature(creature, buff); + + } + + }, (long) buff.getRemainingDuration(), TimeUnit.SECONDS); + continue; + } else { + removeBuffFromCreature(creature, buff); + } + + } + + } + + + +} diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index ace0a2b7..5efad7b3 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -35,6 +35,8 @@ import org.apache.mina.core.session.IoSession; import engine.clients.Client; import engine.resources.common.CRC; +import engine.resources.container.CreatureContainerPermissions; +import engine.resources.container.CreaturePermissions; import engine.resources.database.DatabaseConnection; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; @@ -48,6 +50,7 @@ import protocol.swg.ClientRandomNameResponse; import protocol.swg.ClientVerifyAndLockNameRequest; import protocol.swg.ClientVerifyAndLockNameResponse; import protocol.swg.CreateCharacterSuccess; +import protocol.swg.HeartBeatMessage; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; @@ -205,17 +208,20 @@ public class CharacterService implements INetworkDispatch { String sharedRaceTemplate = raceTemplate.replace("player/", "player/shared_"); CreatureObject object = (CreatureObject) core.objectService.createObject(sharedRaceTemplate, core.terrainService.getPlanetList().get(0)); - object.setCustomizationData(clientCreateCharacter.getCustomizationData()); + object.setContainerPermissions(CreaturePermissions.CREATURE_PERMISSIONS); + object.setCustomization(clientCreateCharacter.getCustomizationData()); object.setCustomName(clientCreateCharacter.getName()); object.setHeight(clientCreateCharacter.getScale()); object.setPersistent(true); - object.setPosition(new Point3D(3608, 5, -4753)); + object.setPosition(new Point3D(-1294, 12, -3590)); + object.setCashCredits(100); + object.setBankCredits(1000); //object.setPosition(new Point3D(0, 0, 0)); - object.setOrientation(new Quaternion(1, 0, 1, 0)); + object.setOrientation(new Quaternion(1, 0, 0, 0)); object.createTransaction(core.getCreatureODB().getEnvironment()); PlayerObject player = (PlayerObject) core.objectService.createObject("object/player/shared_player.iff", object.getPlanet()); - object.add(player); + object._add(player); player.setProfession(clientCreateCharacter.getProfession()); player.setProfessionWheelPosition(clientCreateCharacter.getProfessionWheelPosition()); if(clientCreateCharacter.getHairObject().length() > 0) { @@ -223,33 +229,39 @@ public class CharacterService implements INetworkDispatch { TangibleObject hair = (TangibleObject) core.objectService.createObject(sharedHairTemplate, object.getPlanet()); if(clientCreateCharacter.getHairCustomization().length > 0) hair.setCustomization(clientCreateCharacter.getHairCustomization()); - object.add(hair); + object._add(hair); } TangibleObject inventory = (TangibleObject) core.objectService.createObject("object/tangible/inventory/shared_character_inventory.iff", object.getPlanet()); + inventory.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); TangibleObject appInventory = (TangibleObject) core.objectService.createObject("object/tangible/inventory/shared_appearance_inventory.iff", object.getPlanet()); + appInventory.setContainerPermissions(CreaturePermissions.CREATURE_PERMISSIONS); TangibleObject datapad = (TangibleObject) core.objectService.createObject("object/tangible/datapad/shared_character_datapad.iff", object.getPlanet()); + datapad.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); TangibleObject bank = (TangibleObject) core.objectService.createObject("object/tangible/bank/shared_character_bank.iff", object.getPlanet()); + bank.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); TangibleObject missionBag = (TangibleObject) core.objectService.createObject("object/tangible/mission_bag/shared_mission_bag.iff", object.getPlanet()); - object.add(inventory); - object.add(appInventory); - object.add(datapad); - object.add(bank); - object.add(missionBag); + missionBag.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + + object._add(inventory); + object._add(appInventory); + object._add(datapad); + object._add(bank); + object._add(missionBag); TangibleObject backpack = (TangibleObject) core.objectService.createObject("object/tangible/wearables/backpack/shared_backpack_galactic_marine.iff", object.getPlanet()); - inventory.add(backpack); - object.addObjectToEquipList(datapad); - object.addObjectToEquipList(inventory); + inventory._add(backpack); + //object.addObjectToEquipList(datapad); + //object.addObjectToEquipList(inventory); WeaponObject weapon = (WeaponObject) core.objectService.createObject("object/weapon/ranged/rifle/shared_rifle_a280.iff", object.getPlanet()); WeaponObject defaultWeapon = (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", object.getPlanet()); - object.addObjectToEquipList(defaultWeapon); + //object.addObjectToEquipList(defaultWeapon); - object.add(defaultWeapon); + object._add(defaultWeapon); - object.addObjectToEquipList(weapon); + //object.addObjectToEquipList(weapon); - object.add(weapon); + object._add(weapon); object.setWeaponId(weapon.getObjectID()); core.scriptService.callScript("scripts/", "demo", "CreateStartingCharacter", object); @@ -272,7 +284,7 @@ public class CharacterService implements INetworkDispatch { ps.executeUpdate(); ps.close(); CreateCharacterSuccess success = new CreateCharacterSuccess(object.getObjectID()); - + session.write(new HeartBeatMessage().serialize()); session.write(core.loginService.getLoginCluster().serialize()); session.write(core.loginService.getLoginClusterStatus().serialize()); diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 8fbc152f..2a916b75 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -27,8 +27,12 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.session.IoSession; import protocol.swg.ServerTimeMessage; +import resources.common.Opcodes; +import resources.objects.creature.CreatureObject; +import resources.objects.player.PlayerObject; import main.NGECore; @@ -41,7 +45,7 @@ import engine.resources.service.INetworkRemoteEvent; public class PlayerService implements INetworkDispatch { private NGECore core; - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); public PlayerService(final NGECore core) { this.core = core; @@ -60,13 +64,62 @@ public class PlayerService implements INetworkDispatch { } } - }, 1, 1, TimeUnit.MINUTES); + }, 1, 1, TimeUnit.SECONDS); + } + + public void postZoneIn(final CreatureObject creature) { + + scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + + PlayerObject player = (PlayerObject) creature.getSlottedObject("ghost"); + player.setTotalPlayTime(player.getTotalPlayTime() + 30); + player.setLastPlayTimeUpdate(System.currentTimeMillis()); + + } + + }, 30, 30, TimeUnit.SECONDS); + + scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + + if(creature.getAction() < creature.getMaxAction()) + creature.setAction(creature.getAction() + 200); + + } + + }, 0, 1, TimeUnit.SECONDS); + + scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + + if(creature.getHealth() < creature.getMaxHealth() && creature.getCombatFlag() == 0) + creature.setHealth(creature.getHealth() + 300); + + } + + }, 0, 1, TimeUnit.SECONDS); + } @Override - public void insertOpcodes(Map arg0, - Map arg1) { - // TODO Auto-generated method stub + public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { + + swgOpcodes.put(Opcodes.CmdSceneReady, new INetworkRemoteEvent() { + + @Override + public void handlePacket(IoSession session, IoBuffer buffer) throws Exception { + + + } + + }); } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index e47f5bf1..d1bb145c 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -42,6 +42,8 @@ import engine.clientdata.visitors.MeshVisitor; import engine.clientdata.visitors.PortalVisitor; import engine.clientdata.visitors.PortalVisitor.Cell; import engine.clients.Client; +import engine.resources.common.Mesh3DTriangle; +import engine.resources.common.Ray; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -63,13 +65,22 @@ import protocol.swg.objectControllerObjects.TargetUpdate; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; import resources.common.*; +import toxi.geom.Line3D; +import toxi.geom.Ray3D; +import toxi.geom.Vec3D; +import toxi.geom.mesh.TriangleMesh; import wblut.geom.WB_AABBNode; import wblut.geom.WB_AABBTree; +import wblut.geom.WB_Distance; import wblut.geom.WB_Intersection; import wblut.geom.WB_Point3d; import wblut.geom.WB_Ray; import wblut.geom.WB_Transform; +import wblut.geom.WB_Vector3d; import wblut.hemesh.HE_Mesh; +import wblut.hemesh.HE_Vertex; +import wblut.math.WB_Epsilon; +import wblut.math.WB_M44; @SuppressWarnings("unused") @@ -77,7 +88,8 @@ public class SimulationService implements INetworkDispatch { Map> quadTrees; private NGECore core; - + private Map cellMeshes = new ConcurrentHashMap(); + public SimulationService(NGECore core) { this.core = core; TerrainService terrainService = core.terrainService; @@ -111,7 +123,12 @@ public class SimulationService implements INetworkDispatch { core.commandService.registerCommand("getattributesbatch"); core.commandService.registerCommand("pvp"); core.commandService.registerCommand("setcurrentskilltitle"); - + core.commandService.registerCommand("tip"); + core.commandService.registerCommand("faction"); + core.commandService.registerCommand("setspeed"); + core.commandService.registerCommand("waypoint"); + core.commandService.registerCommand("setwaypointactivestatus"); + core.commandService.registerCommand("setwaypointname"); } public void add(SWGObject object, int x, int y) { @@ -212,7 +229,7 @@ public class SimulationService implements INetworkDispatch { //object.setParent(null); // System.out.println("Parsed Height: " + core.terrainService.getHeight(object.getPlanetId(), dataTransform.getXPosition(), dataTransform.getZPosition()) // + " should be: " + dataTransform.getYPosition()); - UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed(), object.getCombatFlag()); + UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed()); List newAwareObjects = get(object.getPlanet(), newPos.x, newPos.z, 200); ArrayList oldAwareObjects = new ArrayList(object.getAwareObjects()); @@ -275,7 +292,7 @@ public class SimulationService implements INetworkDispatch { Point3D oldPos = object.getPosition(); Quaternion newOrientation = new Quaternion(dataTransform.getWOrientation(), dataTransform.getXOrientation(), dataTransform.getYOrientation(), dataTransform.getZOrientation()); - UpdateTransformWithParentMessage utm = new UpdateTransformWithParentMessage(object.getObjectID(), dataTransform.getCellId(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed(), object.getCombatFlag()); + UpdateTransformWithParentMessage utm = new UpdateTransformWithParentMessage(object.getObjectID(), dataTransform.getCellId(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed()); if(object.getContainer() != parent) { @@ -341,7 +358,7 @@ public class SimulationService implements INetworkDispatch { } - public WB_AABBTree getAABBTree(SWGObject object, int collisionBlockFlag) { + /*public WB_AABBTree getAABBTree(SWGObject object, int collisionBlockFlag) { if(object.getMeshVisitor() == null || object.getTemplateData() == null) { System.out.println("NULL Mesh Visitor for: " + object.getTemplate()); @@ -350,9 +367,8 @@ public class SimulationService implements INetworkDispatch { if(object.getTemplateData().getAttribute("collisionActionBlockFlags") != null) { int bit = (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags") & collisionBlockFlag; - - if(bit == (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags")) - return null; + //if(bit == (Integer) object.getTemplateData().getAttribute("collisionActionBlockFlags")) + // return null; } Point3D position = object.getPosition(); @@ -360,29 +376,59 @@ public class SimulationService implements INetworkDispatch { if(mesh == null) return null; - System.out.println(object.getHeading()); + float angle = (float) (object.getRadians() * (180 / Math.PI)); System.out.println("Angle: " + angle); Quaternion quat = object.getOrientation(); - WB_Transform transform = new WB_Transform().addRotateZ(object.getRadians()); - mesh = mesh.move(position.x, position.z, position.y).transform(transform); - mesh.clean(); - mesh.cleanUnusedElementsByFace(); + //WB_Transform transform = new WB_Transform(); + //transform.addRotateZ(object.getRadians()); + + //mesh = mesh.transform(transform); + + //mesh = mesh.move(position.x, position.z, position.y); + + WB_AABBTree aabbTree = new WB_AABBTree(mesh, mesh.numberOfFaces()); return aabbTree; - } + }*/ + + public Ray convertRayToModelSpace(Point3D origin, Point3D end, SWGObject object) { - public WB_Ray convertRayToModelSpace(WB_Ray ray, SWGObject object) { + Point3D position = object.getPosition(); + + WB_M44 translateMatrix = new WB_M44(1, 0, 0, position.x, 0, 1, 0, position.y, 0, 0, 1, position.z, 0, 0, 0, 1); - WB_Transform transform = new WB_Transform().addTranslate(new WB_Point3d(-object.getPosition().x, -object.getPosition().z , -object.getPosition().y)).addRotateZ(object.getRadians()); - ray = transform.apply(ray); + float radians = object.getRadians(); + float sin = (float) Math.sin(radians); + 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(); + + 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); + float originZ = (float) (modelSpace.m31 * origin.x + modelSpace.m32 * origin.y + modelSpace.m33 * origin.z + modelSpace.m34); + + origin = new Point3D(originX, originY, originZ); + + float endX = (float) (modelSpace.m11 * end.x + modelSpace.m12 * end.y + modelSpace.m13 * end.z + modelSpace.m14); + float endY = (float) (modelSpace.m21 * end.x + modelSpace.m22 * end.y + modelSpace.m23 * end.z + modelSpace.m24); + float endZ = (float) (modelSpace.m31 * end.x + modelSpace.m32 * end.y + modelSpace.m33 * end.z + modelSpace.m34); + + end = new Point3D(endX, endY, endZ); + + Vector3D direction = new Vector3D(end.x - origin.x, end.y - origin.y, end.z - origin.z); + if(direction.getX() > 0 && direction.getY() > 0 && direction.getZ() > 0) + direction.normalize(); - return ray; + return new Ray(origin, direction); } + public void handleDisconnect(IoSession session) { Client client = core.getClient((Integer) session.getAttribute("connectionId")); @@ -393,17 +439,23 @@ public class SimulationService implements INetworkDispatch { if(client.getParent() == null) return; + session.suspendWrite(); + CreatureObject object = (CreatureObject) client.getParent(); boolean remove = remove(object, object.getPosition().x, object.getPosition().z); if(remove) System.out.println("Successful quadtree remove"); - HashSet oldObservers = new HashSet(object.getObservers()); - for(Iterator it = oldObservers.iterator(); it.hasNext();) { - Client observerClient = it.next(); - if(observerClient.getParent() != null) { - observerClient.getParent().makeUnaware(object); + if(object.getContainer() == null) { + HashSet oldObservers = new HashSet(object.getObservers()); + for(Iterator it = oldObservers.iterator(); it.hasNext();) { + Client observerClient = it.next(); + if(observerClient.getParent() != null && !(observerClient.getSession() == session)) { + observerClient.getParent().makeUnaware(object); + } } + } else { + object.getContainer().remove(object); } @@ -411,10 +463,9 @@ public class SimulationService implements INetworkDispatch { core.getCreatureODB().put(object, Long.class, CreatureObject.class, object.getTransaction()); object.getTransaction().commitSync(); - session.suspendRead(); - session.suspendWrite(); core.objectService.destroyObject(object); core.getActiveConnectionsMap().remove((Integer) session.getAttribute("connectionId")); + } public void handleZoneIn(Client client) { @@ -493,7 +544,7 @@ public class SimulationService implements INetworkDispatch { CmdStartScene startScene = new CmdStartScene((byte) 0, object.getObjectID(), object.getPlanet().getPath(), object.getTemplate(), newPos.x, newPos.y, newPos.z, System.currentTimeMillis() / 1000, object.getRadians()); session.write(startScene.serialize()); - core.simulationService.handleZoneIn(client); + handleZoneIn(client); object.makeAware(object); @@ -513,7 +564,7 @@ public class SimulationService implements INetworkDispatch { if(position.x >= -8192 && position.x <= 8192 && position.z >= -8192 && position.z <= 8192) { - DataTransform dataTransform = new DataTransform(new Point3D(position.x, position.y, position.z), orientation, obj.getMovementCounter(), obj.getObjectID()); + DataTransform dataTransform = new DataTransform(new Point3D(position.x, position.y, position.z), orientation, 1, obj.getObjectID()); ObjControllerMessage objController = new ObjControllerMessage(0x1B, dataTransform); obj.notifyObservers(objController, true); @@ -521,21 +572,18 @@ public class SimulationService implements INetworkDispatch { } - // not fully working yet(rotation of meshes wrong) public boolean checkLineOfSight(SWGObject obj1, SWGObject obj2) { if(obj1.getPlanet() != obj2.getPlanet()) return false; - if((obj1.getContainer() != null && obj2.getContainer() != null) && (obj1.getContainer() == obj2.getContainer())) // if both are in same cell they should always be in sight of each other - return true; - - if(obj1.getGrandparent() != null && obj2.getGrandparent() != null) { + if(obj1.getGrandparent() != null || obj2.getGrandparent() != null) { if(obj1.getGrandparent() == obj2.getGrandparent()) return checkLineOfSightInBuilding(obj1, obj2, obj1.getGrandparent()); - else + else if(obj1.getGrandparent() != null && obj2.getGrandparent() != null) return false; + } float heightOrigin = 1.f; @@ -550,46 +598,48 @@ public class SimulationService implements INetworkDispatch { Point3D position1 = obj1.getWorldPosition(); Point3D position2 = obj2.getWorldPosition(); - Vector3D origin = new Vector3D(position1.x, position1.z, position1.y + heightOrigin); - Vector3D end = new Vector3D(position2.x, position2.z, position2.y + heightDirection); - + 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 + 1); + List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, 150); - - WB_Ray ray = new WB_Ray(origin.getX(), origin.getY() , origin.getZ(), end.getX(), end.getY(), end.getZ()); - for(SWGObject object : inRangeObjects) { if(object == obj1 || object == obj2) continue; - Point3D position = object.getWorldPosition(); - float otherDistance = position.getDistance2D(position1); - System.out.println("Distance from origin to target: " + distance + " Distance from origin to current obj: " + otherDistance); - if(!obj1.inRange(position, distance)) - continue; - - WB_AABBTree aabbTree = getAABBTree(object, 255); - - if(aabbTree == null) - continue; - - //System.out.println(object.getTemplate()); - - //ray = convertRayToModelSpace(ray, object); - - ArrayList collisions = WB_Intersection.getIntersection(ray, aabbTree); - if(!collisions.isEmpty()) { - System.out.println("Collided with " + object.getTemplate() + " X: " + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); - return false; + if(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("Collided with " + object.getTemplate() + " X: " + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); + return false; + } + + } + } - /*if(obj1.getContainer() != null || obj2.getContainer() != null) { + if(obj1.getContainer() != null || obj2.getContainer() != null) { CellObject cell = null; @@ -600,13 +650,26 @@ public class SimulationService implements INetworkDispatch { if(cell != null) return checkLineOfSightWorldToCell(obj1, obj2, cell); - }*/ + } + 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) 0.5, 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 with terrain"); + return false; + } + } + return true; } - // not fully working yet(rotation of meshes wrong) public boolean checkLineOfSightInBuilding(SWGObject obj1, SWGObject obj2, SWGObject building) { PortalVisitor portalVisitor = building.getPortalVisitor(); @@ -616,34 +679,45 @@ public class SimulationService implements INetworkDispatch { Point3D position1 = obj1.getPosition(); Point3D position2 = obj2.getPosition(); - - Vector3D origin = new Vector3D(position1.x, position1.z, position1.y + 1); - Vector3D end = new Vector3D(position2.x, position2.z, position2.y + 1); + Point3D origin = new Point3D(position1.x, position1.y + 1, position1.z); + Point3D end = new Point3D(position2.x, position2.y + 1, position2.z); - //Vector3D direction = end.subtract(origin).normalize(); - - WB_Ray ray = new WB_Ray(origin.getX(), origin.getY(), origin.getZ(), end.getX(), end.getY(), end.getZ()); + Vector3D direction = new Vector3D(end.x - origin.x, end.y - origin.y, end.z - origin.z).normalize(); + float distance = position1.getDistance2D(position2); + Ray ray = new Ray(origin, direction); for(int i = 1; i < portalVisitor.cells.size(); i++) { Cell cell = portalVisitor.cells.get(i); - System.out.println(cell.name); try { - System.out.println(cell.mesh); - MeshVisitor meshVisitor = ClientFileManager.loadFile(cell.mesh, MeshVisitor.class); - WB_AABBTree aabbTree = meshVisitor.getAABBTree(meshVisitor.createMesh()); - if(aabbTree == null) + MeshVisitor meshVisitor; + if(!cellMeshes.containsKey(cell.mesh)) { + meshVisitor = ClientFileManager.loadFile(cell.mesh, MeshVisitor.class); + cellMeshes.put(cell.mesh, meshVisitor); + } else { + meshVisitor = cellMeshes.get(cell.mesh); + } + + if(meshVisitor == null) continue; - ArrayList collisions = WB_Intersection.getIntersection(ray, aabbTree); + List tris = meshVisitor.getTriangles(); + + if(tris.isEmpty()) + continue; - if(!collisions.isEmpty()) { - System.out.println("Collision with: " + cell.name); - return false; + for(Mesh3DTriangle tri : tris) { + + if(ray.intersectsTriangle(tri, distance) != null) { + System.out.println("Collision with: " + cell.name); + return false; + } + } + } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } @@ -654,7 +728,6 @@ public class SimulationService implements INetworkDispatch { } - // not fully working yet(rotation of meshes wrong) public boolean checkLineOfSightWorldToCell(SWGObject obj1, SWGObject obj2, CellObject cell) { SWGObject building = cell.getContainer(); @@ -679,22 +752,33 @@ public class SimulationService implements INetworkDispatch { Point3D position1 = obj1.getWorldPosition(); Point3D position2 = obj2.getWorldPosition(); - Point3D origin = new Point3D(position1.x, position1.z, position1.y + heightOrigin); - Point3D direction = new Point3D(position2.x, position2.z, position2.y + heightDirection); + Point3D origin = new Point3D(position1.x, position1.y + heightOrigin, position1.z); + Point3D end = new Point3D(position2.x, position2.y + heightDirection, position2.z); - WB_Ray ray = new WB_Ray(origin.x, origin.y , origin.z, direction.x, direction.y, direction.z); - ray = convertRayToModelSpace(ray, building); + Ray ray = convertRayToModelSpace(origin, end, building); if(cell.getCellNumber() >= portalVisitor.cellCount) return true; try { + MeshVisitor meshVisitor = ClientFileManager.loadFile(portalVisitor.cells.get(cell.getCellNumber()).mesh, MeshVisitor.class); - WB_AABBTree aabbTree = meshVisitor.getAABBTree(meshVisitor.createMesh()); - ArrayList collisions = WB_Intersection.getIntersection(ray, aabbTree); + + if(meshVisitor == null) + return true; + + List tris = meshVisitor.getTriangles(); + + if(tris.isEmpty()) + return true; - if(!collisions.isEmpty()) - return false; + for(Mesh3DTriangle tri : tris) { + + if(ray.intersectsTriangle(tri) != null) { + return false; + } + + } } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); diff --git a/src/services/StaticService.java b/src/services/StaticService.java index 42019b6b..c06a70ce 100644 --- a/src/services/StaticService.java +++ b/src/services/StaticService.java @@ -21,6 +21,62 @@ ******************************************************************************/ package services; -public class StaticService { +import java.util.Map; + +import main.NGECore; + +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; + +public class StaticService implements INetworkDispatch { + + private NGECore core; + + public StaticService(NGECore core) { + this.core = core; + } + + @Override + public void insertOpcodes(Map arg0, Map arg1) { + + } + + @Override + public void shutdown() { + + } + + public void spawnObject(String template, String planetName, long cellId, float x, float y, float z, float qY, float qW) { + + Planet planet = core.terrainService.getPlanetByName(planetName); + + if(planet == null) { + System.out.println("Cant spawn static object because planet is null"); + return; + } + + SWGObject object = core.objectService.createObject(template, 0, planet, new Point3D(x, y, z), new Quaternion(qW, 0, qY, 0)); + + if(object == null) { + System.out.println("Static object is null"); + return; + } + + if(cellId == 0) + core.simulationService.add(object, x, z); + else { + SWGObject parent = core.objectService.getObject(cellId); + if(parent == null) { + System.out.println("Cell not found"); + return; + } + parent.add(object); + } + + } } diff --git a/src/services/TerrainService.java b/src/services/TerrainService.java index a7a28a48..492905fd 100644 --- a/src/services/TerrainService.java +++ b/src/services/TerrainService.java @@ -68,7 +68,6 @@ public class TerrainService { return Float.NaN; Planet planet = getPlanetByID(planetId); float height = planet.getTerrainVisitor().getHeight(x, z); - System.out.println("Height: " + height); return height; } diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index 52e68333..fecb6110 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -229,7 +229,7 @@ public class ChatService implements INetworkDispatch { mail.setStatus(Mail.NEW); mail.setSubject(packet.getSubject()); mail.setTimeStamp((int) (date.getTime() / 1000)); - + mail.setAttachments(packet.getWaypointAttachments()); storePersistentMessage(mail); if(recipient.getClient() != null) { @@ -324,7 +324,7 @@ public class ChatService implements INetworkDispatch { //System.out.println(config.getString("GALAXY_NAME")); ChatPersistentMessageToClient msg = new ChatPersistentMessageToClient(mail.getSenderName(), config.getString("GALAXY_NAME"), mail.getMailId() - ,(byte) 1, "", mail.getSubject(), mail.getStatus(), mail.getTimeStamp()); + ,(byte) 1, "", mail.getSubject(), mail.getStatus(), mail.getTimeStamp(), mail.getAttachments()); client.getSession().write(msg.serialize()); } @@ -343,7 +343,7 @@ public class ChatService implements INetworkDispatch { //System.out.println(config.getString("GALAXY_NAME")); ChatPersistentMessageToClient msg = new ChatPersistentMessageToClient(mail.getSenderName(), config.getString("GALAXY_NAME"), mail.getMailId() - ,(byte) 0, mail.getMessage(), mail.getSubject(), mail.getStatus(), mail.getTimeStamp()); + ,(byte) 0, mail.getMessage(), mail.getSubject(), mail.getStatus(), mail.getTimeStamp(), mail.getAttachments()); client.getSession().write(msg.serialize()); } diff --git a/src/services/chat/Mail.java b/src/services/chat/Mail.java index cf811a62..5709a059 100644 --- a/src/services/chat/Mail.java +++ b/src/services/chat/Mail.java @@ -21,10 +21,11 @@ ******************************************************************************/ package services.chat; +import java.util.List; import com.sleepycat.persist.model.Entity; import com.sleepycat.persist.model.PrimaryKey; -@Entity +@Entity(version=1) public class Mail { @PrimaryKey @@ -35,6 +36,7 @@ public class Mail { private String message; private byte status; private int timeStamp; + private List attachments; public static final byte NEW = 0x4E; public static final byte READ = 0x52; @@ -114,5 +116,15 @@ public class Mail { public void setTimeStamp(int timeStamp) { this.timeStamp = timeStamp; } + + + public List getAttachments() { + return attachments; + } + + + public void setAttachments(List attachments) { + this.attachments = attachments; + } } diff --git a/src/services/chat/WaypointAttachment.java b/src/services/chat/WaypointAttachment.java new file mode 100644 index 00000000..314cb08f --- /dev/null +++ b/src/services/chat/WaypointAttachment.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.chat; + +import com.sleepycat.persist.model.Persistent; + +@Persistent +public class WaypointAttachment { + + public WaypointAttachment() { } + + public long cellID; + public int planetCRC; + public float positionX; + public float positionY; + public float positionZ; + public byte color; + public boolean active; + public String name; + +} diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index ba91f070..64da30c8 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -21,6 +21,503 @@ ******************************************************************************/ package services.combat; -public class CombatService { +import java.util.Map; +import java.util.Random; +import protocol.swg.ObjControllerMessage; +import protocol.swg.objectControllerObjects.CombatAction; +import protocol.swg.objectControllerObjects.CommandEnqueueRemove; +import protocol.swg.objectControllerObjects.StartTask; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.command.CombatCommand; +import main.NGECore; +import engine.resources.common.CRC; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class CombatService implements INetworkDispatch { + + private NGECore core; + + public CombatService(NGECore core) { + this.core = core; + core.commandService.registerCombatCommand("rangedshotrifle"); + core.commandService.registerCombatCommand("rangedshotpistol"); + core.commandService.registerCombatCommand("rangedshotlightrifle"); + core.commandService.registerCombatCommand("rangedshot"); + core.commandService.registerCombatCommand("meleehit"); + core.commandService.registerCombatCommand("saberhit"); + core.commandService.registerCombatCommand("fs_sweep_7"); + core.commandService.registerCombatCommand("fs_dm_7"); + core.commandService.registerCombatCommand("fs_dm_cc_6"); + core.commandService.registerCombatCommand("fs_ae_dm_cc_6"); + } + + @Override + public void insertOpcodes(Map arg0, Map arg1) { + + } + + @Override + public void shutdown() { + // TODO Auto-generated method stub + + } + + public void doCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + + if(!applySpecialCost(attacker, weapon, command)) + return; + + if(!attemptCombat(attacker, target)) + return; + + if(command.getAttackType() == 1) + doSingleTargetCombat(attacker, target, weapon, command, actionCounter); + else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + doAreaCombat(attacker, target, weapon, command, actionCounter); + + } + + private void doAreaCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + if(target instanceof CreatureObject) { + doAreaCombat(attacker, (CreatureObject) target, weapon, command, actionCounter); + return; + } + } + + private void doSingleTargetCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + if(target instanceof CreatureObject) { + doSingleTargetCombat(attacker, (CreatureObject) target, weapon, command, actionCounter); + return; + } + + float damage = calculateDamage(attacker, target, weapon, command); + } + + private void doAreaCombat(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + } + + private void doSingleTargetCombat(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + float damage = calculateDamage(attacker, target, weapon, command); + + byte hitType = getHitType(attacker, target, weapon, command); + + switch(hitType) { + + case HitType.MISS: + damage = 0; + break; + + case HitType.DODGE: + damage = 0; + break; + + case HitType.PARRY: + damage = 0; + break; + + case HitType.CRITICAL: + damage *= 1.5f; + break; + + } + byte mitigationType = -1; + if(hitType == HitType.CRITICAL || hitType == HitType.HIT || hitType == HitType.STRIKETHROUGH) { + mitigationType = doMitigationRolls(attacker, target, weapon, command, hitType); + + if(mitigationType == HitType.GLANCE) { + damage *= 0.4f; + } else if(mitigationType == HitType.EVASION) { + float evasionValue = (attacker.getSkillMod("combat_evasion_value").getBase() / 4) / 100; + + damage *= (1 - evasionValue); + + } + + } + damage *= (1 - getArmorReduction(attacker, target, weapon, command, hitType)); + if(mitigationType == HitType.BLOCK) { + + float blockValue = (attacker.getSkillMod("strength_modified").getBase() * attacker.getSkillMod("combat_block_value").getBase()) / 2 + 25; + damage -= blockValue; + + } + + if(damage > 0) + applyDamage(attacker, target, (int) damage); + + sendCombatPackets(attacker, target, weapon, command, actionCounter); + + } + + + + private void sendCombatPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + String animationStr = command.getRandomAnimation(weapon); + CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); + attacker.notifyObserversInRange(objController, true, 125); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); + attacker.getClient().getSession().write(objController2.serialize()); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); + ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); + attacker.getClient().getSession().write(objController3.serialize()); + + } + + private float getArmorReduction(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, byte hitType) { + + int elementalType = 1; + + if(command.getPercentFromWeapon() > 0) { + + // TODO: elemental mitigation and damage + + if(weapon.getStringAttribute("cat_wpn_damage.wpn_damage_type").equals("@obj_attr_n:armor_eff_kinetic")) + elementalType = ElementalType.KINETIC; + else if(weapon.getStringAttribute("cat_wpn_damage.wpn_damage_type").equals("@obj_attr_n:armor_eff_energy")) + elementalType = ElementalType.ENERGY; + + } else { + + elementalType = command.getElementalType(); + + } + + int baseArmor = 0; + + switch(elementalType) { + + case ElementalType.KINETIC: + baseArmor = target.getSkillMod("kinetic").getBase(); + case ElementalType.ENERGY: + baseArmor = target.getSkillMod("energy").getBase(); + case ElementalType.HEAT: + baseArmor = target.getSkillMod("heat").getBase(); + case ElementalType.COLD: + baseArmor = target.getSkillMod("cold").getBase(); + case ElementalType.ACID: + baseArmor = target.getSkillMod("acid").getBase(); + case ElementalType.ELECTRICITY: + baseArmor = target.getSkillMod("electricity").getBase(); + + } + + float mitigation = (float) (90 * (1 - Math.exp(-0.000125 * baseArmor)) + baseArmor / 9000); + + if(hitType == HitType.STRIKETHROUGH) { + + float stMaxValue = attacker.getSkillMod("combat_strikethrough_value").getBase() / 2; + float stMinValue = stMaxValue / 2; + + float stValue = new Random().nextInt((int) (stMaxValue - stMinValue + 1)) + stMinValue; + stValue /= 100; + mitigation *= stValue; + } + + return mitigation / 100; + + } + + private boolean attemptCombat(CreatureObject attacker, TangibleObject target) { + + if(target.getDefendersList().contains(attacker) && attacker.getDefendersList().contains(target)) + return true; + + if(attacker.getStateBitmask() == 0x8000000) + return false; + + if(!target.isAttackableBy(attacker)) + return false; + + target.addDefender(attacker); + attacker.addDefender(target); + + return true; + + } + + private boolean applySpecialCost(CreatureObject attacker, WeaponObject weapon, CombatCommand command) { + + float actionCost = command.getActionCost(); + float healthCost = command.getHealthCost(); + + if(actionCost == 0 && healthCost == 0) + return true; + + float newAction = attacker.getAction() - actionCost; + if(newAction <= 0) + return false; + + float newHealth = attacker.getHealth() - healthCost; + if(newHealth <= 0) + return false; + + if(newAction != attacker.getAction()) + attacker.setAction((int) newAction); + + if(newHealth != attacker.getHealth()) + attacker.setHealth((int) newHealth); + + return true; + + } + + private float calculateDamage(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + + if(command.getPercentFromWeapon() > 0 && weapon != attacker.getSlottedObject("default_weapon")) { + + float weaponMinDmg = weapon.getIntAttribute("cat_wpn_damage.wpn_damage_min"); + float weaponMaxDmg = weapon.getIntAttribute("cat_wpn_damage.wpn_damage_max"); + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + if(weapon.isMelee() && attacker.getSkillMod("strength_modified") != null) { + + if(attacker.getSkillMod("strength_modified").getBase() > 0) { + rawDamage += ((attacker.getSkillMod("strength_modified").getBase() / 100) * 33); + } + + } + + } else if(command.getPercentFromWeapon() > 0) { + + float weaponMinDmg = 50; + float weaponMaxDmg = 100; + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + if(weapon.isMelee() && attacker.getSkillMod("strength_modified") != null) { + + if(attacker.getSkillMod("strength_modified").getBase() > 0) { + rawDamage += ((attacker.getSkillMod("strength_modified").getBase() / 100) * 33); + } + + } + + } + + if(target.getSkillMod("damage_decrease_percentage") != null) { + rawDamage *= (target.getSkillMod("damage_decrease_percentage").getBase() / 100); + } + + return rawDamage; + + } + + + private float calculateDamage(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + + if(command.getPercentFromWeapon() > 0 && weapon != attacker.getSlottedObject("default_weapon")) { + + float weaponMinDmg = weapon.getIntAttribute("cat_wpn_damage.wpn_damage_min"); + float weaponMaxDmg = weapon.getIntAttribute("cat_wpn_damage.wpn_damage_max"); + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + if(weapon.isMelee() && attacker.getSkillMod("strength_modified") != null) { + + if(attacker.getSkillMod("strength_modified").getBase() > 0) { + rawDamage += ((attacker.getSkillMod("strength_modified").getBase() / 100) * 33); + } + + } + + } else if(command.getPercentFromWeapon() > 0) { + + float weaponMinDmg = 50; + float weaponMaxDmg = 100; + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + if(weapon.isMelee() && attacker.getSkillMod("strength_modified") != null) { + + if(attacker.getSkillMod("strength_modified").getBase() > 0) { + rawDamage += ((attacker.getSkillMod("strength_modified").getBase() / 100) * 33); + } + + } + + } + + return rawDamage; + + } + + public byte getHitType(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) { + + Random rand = new Random(); + float r; + + // negation rolls(parry, miss and dodge) can only roll on single target attacks, strikethrough also only rolls on single target attacks + if(command.getAttackType() == 1) { + + if(weapon.isRanged()) { + float missChance = 0.5f; + if(attacker.getSkillMod("strength_modified").getBase() > 0) { + float missNegation = (float) ((attacker.getSkillMod("strength_modified").getBase() / 100) * 0.1); + if(missNegation > 0.4f) + missNegation = 0.4f; + missChance -= missNegation; + } + r = rand.nextFloat(); + if(r <= missChance) + return HitType.MISS; + } + float dodgeChance = target.getSkillMod("display_only_dodge").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= dodgeChance) + return HitType.DODGE; + + + WeaponObject weapon2 = (WeaponObject) core.objectService.getObject(((CreatureObject) target).getWeaponId()); + if(weapon2 != null && weapon2.isMelee()) { + + float parryChance = target.getSkillMod("display_only_parry").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= parryChance) + return HitType.PARRY; + + } + + float stChance = attacker.getSkillMod("display_only_strikethrough").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= stChance) + return HitType.STRIKETHROUGH; + + } + + float critChance = attacker.getSkillMod("display_only_critical").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= critChance) + return HitType.CRITICAL; + + // TODO: Punishing blow once AI is implemented + + return HitType.HIT; + + } + + public byte doMitigationRolls(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, byte hitType) { + + Random rand = new Random(); + float r; + + float blockChance = target.getSkillMod("display_only_block").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= blockChance) + return HitType.BLOCK; + + if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) { + + float evasionChance = target.getSkillMod("display_only_evasion").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= evasionChance) + return HitType.EVASION; + + } + + if(hitType == HitType.HIT) { + + float glanceChance = target.getSkillMod("display_only_glancing_blow").getBase() / 10000; + + r = rand.nextFloat(); + if(r <= glanceChance) + return HitType.GLANCE; + + } + + + return -1; + + } + + public void applyDamage(CreatureObject attacker, CreatureObject target, int damage) { + + if(target.getHealth() - damage <= 0) { + target.setHealth(1); + target.setPosture((byte) 13); + if(target.getSlottedObject("ghost") != null) + attacker.sendSystemMessage("You incapacitate " + target.getCustomName() + ".", (byte) 0); + return; + } + target.setHealth(target.getHealth() - damage); + + } + + private boolean isInConeAngle(CreatureObject attacker, CreatureObject target, int coneLength, int coneWidth, float directionX, float directionZ) { + + float radius = coneWidth / 2; + float angle = (float) (2 * Math.atan(coneLength / radius)); + + float targetX = target.getWorldPosition().x - attacker.getWorldPosition().x; + float targetZ = target.getWorldPosition().z - attacker.getWorldPosition().z; + + float targetAngle = (float) (Math.atan2(targetZ, targetX) - Math.atan2(directionZ, directionX)); + + float degrees = (float) (targetAngle * 180 / Math.PI); + float coneAngle = angle / 2; + + if(degrees > coneAngle || degrees < -coneAngle) + return false; + + return true; + + } + + + + public enum HitType{; + + public static final byte MISS = 0; + public static final byte DODGE = 1; + public static final byte PARRY = 2; + public static final byte STRIKETHROUGH = 3; + public static final byte CRITICAL = 4; + public static final byte PUNISHING = 5; + public static final byte HIT = 6; + public static final byte BLOCK = 7; + public static final byte EVASION = 8; + public static final byte GLANCE = 9; + + } + + public enum ElementalType {; + + public static final int KINETIC = 1; + public static final int ENERGY = 2; + public static final int BLAST = 4; + public static final int STUN = 8; + public static final int HEAT = 32; + public static final int COLD = 64; + public static final int ACID = 128; + public static final int ELECTRICITY = 256; + + } } diff --git a/src/services/command/CombatCommand.java b/src/services/command/CombatCommand.java new file mode 100644 index 00000000..41cbcedb --- /dev/null +++ b/src/services/command/CombatCommand.java @@ -0,0 +1,590 @@ +/******************************************************************************* + * 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.command; + +import java.util.Random; + +import resources.objects.weapon.WeaponObject; +import engine.clientdata.ClientFileManager; +import engine.clientdata.visitors.DatatableVisitor; + +public class CombatCommand extends BaseSWGCommand { + + private String[] defaultAnimations = new String[]{}; + private String[] oneHandedAnimations = new String[]{}; + private String[] twoHandedAnimations = new String[]{}; + private String[] polearmAnimations = new String[]{}; + private String[] unarmedAnimations = new String[]{}; + private String[] pistolAnimations = new String[]{}; + private String[] carbineAnimations = new String[]{}; + private String[] lightRifleAnimations = new String[]{}; + private String[] rifleAnimations = new String[]{}; + private String[] heavyWpnAnimations = new String[]{}; + private String[] oneHandedLSAnimations = new String[]{}; + private String[] twoHandedLSAnimations = new String[]{}; + private String[] polearmLSAnimations = new String[]{}; + private String[] thrownAnimations = new String[]{}; + private byte validTargetType; + private byte hitType; + private byte healType; + private byte attackType; + private float coneLength; + private float coneWidth; + private float minRange; + private float maxRange; + private int addedDamage, flatActionDamage; + private float percentFromWeapon; + private float bypassArmor; + private float healthCost; + private float actionCost; + private String dotType; + private int dotDuration, dotIntensity; + private String buffNameTarget, buffNameSelf; + private float buffStrengthTarget, buffStrengthSelf, buffDurationTarget, buffDurationSelf; + private boolean canBePunishing; + private int minDamage, maxDamage; + private byte weaponType, weaponCategory; + private float maxRangeOverload; + private int damageType, elementalType, elementalValue; + private String performanceSpam; + private byte hitSpam; + + public CombatCommand(String commandName) { + super(commandName); + try { + DatatableVisitor visitor = ClientFileManager.loadFile("datatables/combat/combat_data.iff", DatatableVisitor.class); + + for(int i = 0; i < visitor.getRowCount(); i++) { + if(visitor.getObject(i, 0) != null) + if(((String) visitor.getObject(i, 0)).equalsIgnoreCase(commandName)) { + + validTargetType = ((Integer) visitor.getObject(i, 5)).byteValue(); + hitType = ((Integer) visitor.getObject(i, 6)).byteValue(); + healType = ((Integer) visitor.getObject(i, 7)).byteValue(); + String defaultAnims = (String) visitor.getObject(i, 21); + setDefaultAnimations(defaultAnims.split(",")); + String unarmedAnims = (String) visitor.getObject(i, 22); + setUnarmedAnimations(unarmedAnims.split(",")); + String oneHAnims = (String) visitor.getObject(i, 23); + setOneHandedAnimations(oneHAnims.split(",")); + String twoHAnims = (String) visitor.getObject(i, 24); + setTwoHandedAnimations(twoHAnims.split(",")); + String polearmAnims = (String) visitor.getObject(i, 25); + setPolearmAnimations(polearmAnims.split(",")); + String pistolAnims = (String) visitor.getObject(i, 26); + setPistolAnimations(pistolAnims.split(",")); + String lightRifleAnims = (String) visitor.getObject(i, 27); + setLightRifleAnimations(lightRifleAnims.split(",")); + String carbineAnims = (String) visitor.getObject(i, 28); + setCarbineAnimations(carbineAnims.split(",")); + String rifleAnims = (String) visitor.getObject(i, 29); + setRifleAnimations(rifleAnims.split(",")); + String heavyAnims = (String) visitor.getObject(i, 30); + setHeavyWpnAnimations(heavyAnims.split(",")); + String thrownAnims = (String) visitor.getObject(i, 31); + setThrownAnimations(thrownAnims.split(",")); + String oneHandLSAnims = (String) visitor.getObject(i, 32); + setOneHandedLSAnimations(oneHandLSAnims.split(",")); + String twoHandLSAnims = (String) visitor.getObject(i, 33); + setTwoHandedLSAnimations(twoHandLSAnims.split(",")); + String polearmLSAnims = (String) visitor.getObject(i, 34); + setPolearmLSAnimations(polearmLSAnims.split(",")); + attackType = ((Integer) visitor.getObject(i, 40)).byteValue(); + coneLength = (Float) visitor.getObject(i, 41); + coneWidth = (Float) visitor.getObject(i, 42); + minRange = (Float) visitor.getObject(i, 43); + maxRange = (Float) visitor.getObject(i, 44); + addedDamage = (Integer) visitor.getObject(i, 45); + flatActionDamage = (Integer) visitor.getObject(i, 46); + percentFromWeapon = (Float) visitor.getObject(i, 47); + bypassArmor = (Float) visitor.getObject(i, 48); + healthCost = (Float) visitor.getObject(i, 54); + actionCost = (Float) visitor.getObject(i, 55); + dotType = (String) visitor.getObject(i, 60); + dotIntensity = (Integer) visitor.getObject(i, 61); + dotDuration = (Integer) visitor.getObject(i, 62); + buffNameTarget = (String) visitor.getObject(i, 63); + buffStrengthTarget = (Float) visitor.getObject(i, 64); + buffDurationTarget = (Float) visitor.getObject(i, 65); + buffNameSelf = (String) visitor.getObject(i, 66); + buffStrengthSelf = (Float) visitor.getObject(i, 67); + buffDurationSelf = (Float) visitor.getObject(i, 68); + canBePunishing = (Integer) visitor.getObject(i, 69) != null; + minDamage = (Integer) visitor.getObject(i, 77); + maxDamage = (Integer) visitor.getObject(i, 78); + maxRangeOverload = (Float) visitor.getObject(i, 79); + weaponCategory = ((Integer) visitor.getObject(i, 80)).byteValue(); + damageType = ((Integer) visitor.getObject(i, 81)).byteValue(); + elementalType = ((Integer) visitor.getObject(i, 82)).byteValue(); + elementalValue = (Integer) visitor.getObject(i, 83); + performanceSpam = (String) visitor.getObject(i, 89); + hitSpam = ((Integer) visitor.getObject(i, 90)).byteValue(); + + } + } + + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + public String[] getDefaultAnimations() { + return defaultAnimations; + } + + public void setDefaultAnimations(String[] defaultAnimations) { + this.defaultAnimations = defaultAnimations; + } + + public String[] getOneHandedAnimations() { + return oneHandedAnimations; + } + + public void setOneHandedAnimations(String[] oneHandedAnimations) { + this.oneHandedAnimations = oneHandedAnimations; + } + + public String[] getTwoHandedAnimations() { + return twoHandedAnimations; + } + + public void setTwoHandedAnimations(String[] twoHandedAnimations) { + this.twoHandedAnimations = twoHandedAnimations; + } + + public String[] getPolearmAnimations() { + return polearmAnimations; + } + + public void setPolearmAnimations(String[] polearmAnimations) { + this.polearmAnimations = polearmAnimations; + } + + public String[] getUnarmedAnimations() { + return unarmedAnimations; + } + + public void setUnarmedAnimations(String[] unarmedAnimations) { + this.unarmedAnimations = unarmedAnimations; + } + + public String[] getPistolAnimations() { + return pistolAnimations; + } + + public void setPistolAnimations(String[] pistolAnimations) { + this.pistolAnimations = pistolAnimations; + } + + public String[] getCarbineAnimations() { + return carbineAnimations; + } + + public void setCarbineAnimations(String[] carbineAnimations) { + this.carbineAnimations = carbineAnimations; + } + + public String[] getLightRifleAnimations() { + return lightRifleAnimations; + } + + public void setLightRifleAnimations(String[] lightRifleAnimations) { + this.lightRifleAnimations = lightRifleAnimations; + } + + public String[] getRifleAnimations() { + return rifleAnimations; + } + + public void setRifleAnimations(String[] rifleAnimations) { + this.rifleAnimations = rifleAnimations; + } + + public String[] getHeavyWpnAnimations() { + return heavyWpnAnimations; + } + + public void setHeavyWpnAnimations(String[] heavyWpnAnimations) { + this.heavyWpnAnimations = heavyWpnAnimations; + } + + public String[] getOneHandedLSAnimations() { + return oneHandedLSAnimations; + } + + public void setOneHandedLSAnimations(String[] oneHandedLSAnimations) { + this.oneHandedLSAnimations = oneHandedLSAnimations; + } + + public String[] getTwoHandedLSAnimations() { + return twoHandedLSAnimations; + } + + public void setTwoHandedLSAnimations(String[] twoHandedLSAnimations) { + this.twoHandedLSAnimations = twoHandedLSAnimations; + } + + public String[] getPolearmLSAnimations() { + return polearmLSAnimations; + } + + public void setPolearmLSAnimations(String[] polearmLSAnimations) { + this.polearmLSAnimations = polearmLSAnimations; + } + + public String[] getThrownAnimations() { + return thrownAnimations; + } + + public void setThrownAnimations(String[] thrownAnimations) { + this.thrownAnimations = thrownAnimations; + } + + public byte getValidTargetType() { + return validTargetType; + } + + public void setValidTargetType(byte validTargetType) { + this.validTargetType = validTargetType; + } + + public byte getHitType() { + return hitType; + } + + public void setHitType(byte hitType) { + this.hitType = hitType; + } + + public byte getHealType() { + return healType; + } + + public void setHealType(byte healType) { + this.healType = healType; + } + + public byte getAttackType() { + return attackType; + } + + public void setAttackType(byte attackType) { + this.attackType = attackType; + } + + public float getConeLength() { + return coneLength; + } + + public void setConeLength(float coneLength) { + this.coneLength = coneLength; + } + + public float getConeWidth() { + return coneWidth; + } + + public void setConeWidth(float coneWidth) { + this.coneWidth = coneWidth; + } + + public float getMinRange() { + return minRange; + } + + public void setMinRange(float minRange) { + this.minRange = minRange; + } + + public float getMaxRange() { + return maxRange; + } + + public void setMaxRange(float maxRange) { + this.maxRange = maxRange; + } + + public int getAddedDamage() { + return addedDamage; + } + + public void setAddedDamage(int addedDamage) { + this.addedDamage = addedDamage; + } + + public int getFlatActionDamage() { + return flatActionDamage; + } + + public void setFlatActionDamage(int flatActionDamage) { + this.flatActionDamage = flatActionDamage; + } + + public float getPercentFromWeapon() { + return percentFromWeapon; + } + + public void setPercentFromWeapon(float percentFromWeapon) { + this.percentFromWeapon = percentFromWeapon; + } + + public float isBypassArmor() { + return bypassArmor; + } + + public void setBypassArmor(float bypassArmor) { + this.bypassArmor = bypassArmor; + } + + public float getHealthCost() { + return healthCost; + } + + public void setHealthCost(float healthCost) { + this.healthCost = healthCost; + } + + public float getActionCost() { + return actionCost; + } + + public void setActionCost(float actionCost) { + this.actionCost = actionCost; + } + + public String getDotType() { + return dotType; + } + + public void setDotType(String dotType) { + this.dotType = dotType; + } + + public int getDotDuration() { + return dotDuration; + } + + public void setDotDuration(int dotDuration) { + this.dotDuration = dotDuration; + } + + public int getDotIntensity() { + return dotIntensity; + } + + public void setDotIntensity(int dotIntensity) { + this.dotIntensity = dotIntensity; + } + + public String getBuffNameTarget() { + return buffNameTarget; + } + + public void setBuffNameTarget(String buffNameTarget) { + this.buffNameTarget = buffNameTarget; + } + + public String getBuffNameSelf() { + return buffNameSelf; + } + + public void setBuffNameSelf(String buffNameSelf) { + this.buffNameSelf = buffNameSelf; + } + + public float getBuffStrengthTarget() { + return buffStrengthTarget; + } + + public void setBuffStrengthTarget(float buffStrengthTarget) { + this.buffStrengthTarget = buffStrengthTarget; + } + + public float getBuffStrengthSelf() { + return buffStrengthSelf; + } + + public void setBuffStrengthSelf(float buffStrengthSelf) { + this.buffStrengthSelf = buffStrengthSelf; + } + + public float getBuffDurationTarget() { + return buffDurationTarget; + } + + public void setBuffDurationTarget(float buffDurationTarget) { + this.buffDurationTarget = buffDurationTarget; + } + + public float getBuffDurationSelf() { + return buffDurationSelf; + } + + public void setBuffDurationSelf(float buffDurationSelf) { + this.buffDurationSelf = buffDurationSelf; + } + + public boolean isCanBePunishing() { + return canBePunishing; + } + + public void setCanBePunishing(boolean canBePunishing) { + this.canBePunishing = canBePunishing; + } + + public int getMinDamage() { + return minDamage; + } + + public void setMinDamage(int minDamage) { + this.minDamage = minDamage; + } + + public int getMaxDamage() { + return maxDamage; + } + + public void setMaxDamage(int maxDamage) { + this.maxDamage = maxDamage; + } + + public byte getWeaponType() { + return weaponType; + } + + public void setWeaponType(byte weaponType) { + this.weaponType = weaponType; + } + + public byte getWeaponCategory() { + return weaponCategory; + } + + public void setWeaponCategory(byte weaponCategory) { + this.weaponCategory = weaponCategory; + } + + public float getMaxRangeOverload() { + return maxRangeOverload; + } + + public void setMaxRangeOverload(float maxRangeOverload) { + this.maxRangeOverload = maxRangeOverload; + } + + public int getDamageType() { + return damageType; + } + + public void setDamageType(int damageType) { + this.damageType = damageType; + } + + public int getElementalType() { + return elementalType; + } + + public void setElementalType(int elementalType) { + this.elementalType = elementalType; + } + + public int getElementalValue() { + return elementalValue; + } + + public void setElementalValue(int elementalValue) { + this.elementalValue = elementalValue; + } + + public String getPerformanceSpam() { + return performanceSpam; + } + + public void setPerformanceSpam(String performanceSpam) { + this.performanceSpam = performanceSpam; + } + + public byte getHitSpam() { + return hitSpam; + } + + public void setHitSpam(byte hitSpam) { + this.hitSpam = hitSpam; + } + + public String getRandomAnimation(WeaponObject weapon) { + + int weaponType = weapon.getWeaponType(); + String[] animations; + + switch(weaponType) { + + case 0: + animations = rifleAnimations; + break; + case 1: + animations = carbineAnimations; + break; + case 2: + animations = pistolAnimations; + break; + case 3: + animations = heavyWpnAnimations; + break; + case 4: + animations = oneHandedAnimations; + break; + case 5: + animations = twoHandedAnimations; + break; + case 6: + animations = unarmedAnimations; + break; + case 7: + animations = polearmAnimations; + break; + case 8: + animations = thrownAnimations; + break; + case 9: + animations = oneHandedLSAnimations; + break; + case 10: + animations = twoHandedLSAnimations; + break; + case 11: + animations = polearmLSAnimations; + break; + + default: + animations = unarmedAnimations; + break; + + } + + return animations[new Random().nextInt(animations.length)]; + + } + + + +} diff --git a/src/services/command/CommandService.java b/src/services/command/CommandService.java index 872f7ff2..5ae2a041 100644 --- a/src/services/command/CommandService.java +++ b/src/services/command/CommandService.java @@ -32,13 +32,19 @@ import org.apache.mina.core.session.IoSession; import engine.clients.Client; import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; import resources.common.*; +import protocol.swg.ObjControllerMessage; import protocol.swg.objectControllerObjects.CommandEnqueue; +import protocol.swg.objectControllerObjects.CommandEnqueueRemove; +import protocol.swg.objectControllerObjects.ShowFlyText; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; public class CommandService implements INetworkDispatch { @@ -69,17 +75,12 @@ public class CommandService implements INetworkDispatch { CommandEnqueue commandEnqueue = new CommandEnqueue(); commandEnqueue.deserialize(data); - //System.out.println(commandEnqueue.getCommandArguments()); - BaseSWGCommand command = getCommandByCRC(commandEnqueue.getCommandCRC()); if(command == null) return; - //if(command.getCommandCRC() == CRC.StringtoCRC("transferitemmisc")) - //System.out.println(commandEnqueue.getCommandArguments()); - // TODO: command filters for state, posture etc. if(client.getParent() == null) { @@ -91,23 +92,37 @@ public class CommandService implements INetworkDispatch { SWGObject target = core.objectService.getObject(commandEnqueue.getTargetID()); - //if(target == null) - //System.out.println("NULL Target"); - + if(command instanceof CombatCommand) { + processCombatCommand(actor, target, (CombatCommand) command, commandEnqueue.getActionCounter()); + return; + } + + core.scriptService.callScript("scripts/commands/", command.getCommandName(), "run", core, actor, target, commandEnqueue.getCommandArguments()); } - - + }); } - public void registerCommand(String name) { + public BaseSWGCommand registerCommand(String name) { BaseSWGCommand command = new BaseSWGCommand(name); commandLookup.add(command); + + return command; + + } + + public CombatCommand registerCombatCommand(String name) { + + CombatCommand command = new CombatCommand(name); + commandLookup.add(command); + + return command; + } public BaseSWGCommand getCommandByCRC(int CRC) { @@ -122,6 +137,66 @@ public class CommandService implements INetworkDispatch { } + private void processCombatCommand(CreatureObject attacker, SWGObject target, CombatCommand command, int actionCounter) { + + boolean success = true; + + if(target == null || !(target instanceof TangibleObject) || target == attacker) + success = false; + + if(attacker.getPosture() == 13 || attacker.getPosture() == 14) + success = false; + + if(target instanceof CreatureObject) { + if(((CreatureObject) target).getPosture() == 13 || ((CreatureObject) target).getPosture() == 14) + success = false; + } + + WeaponObject weapon; + + if(attacker.getWeaponId() == 0) + weapon = (WeaponObject) attacker.getSlottedObject("default_weapon"); // use unarmed/default weapon if no weapon is equipped + else + weapon = (WeaponObject) core.objectService.getObject(attacker.getWeaponId()); + + 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(!core.simulationService.checkLineOfSight(attacker, target)) { + + ShowFlyText los = new ShowFlyText(attacker.getObjectID(), attacker.getObjectID(), "combat_effects", "cant_see", (float) 1.5, (float) 429664.031250); + ObjControllerMessage objController = new ObjControllerMessage(0x1B, los); + attacker.getClient().getSession().write(objController.serialize()); + success = false; + + } + + if(!success) { + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); + ObjControllerMessage objController = new ObjControllerMessage(0x0B, commandRemove); + attacker.getClient().getSession().write(objController.serialize()); + } else { + core.combatService.doCombat(attacker, (TangibleObject) target, weapon, command, actionCounter); + } + + } + + @Override public void shutdown() { // TODO Auto-generated method stub diff --git a/src/services/guild/GuildService.java b/src/services/guild/GuildService.java index 36810c33..304adf76 100644 --- a/src/services/guild/GuildService.java +++ b/src/services/guild/GuildService.java @@ -26,15 +26,19 @@ import java.util.Map; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; +import protocol.swg.CmdSceneReady; + import resources.common.Opcodes; import resources.guild.Guild; import resources.objects.SWGList; +import resources.objects.creature.CreatureObject; import resources.objects.guild.GuildObject; import main.NGECore; import engine.clients.Client; import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; @@ -126,10 +130,10 @@ public class GuildService implements INetworkDispatch { @Override public void handlePacket(IoSession session, IoBuffer data) throws Exception { Client client = core.getClient((Integer) session.getAttribute("connectionId")); - - object.sendCreate(client); - object.sendBaselines(client); - object.sendSceneEndBaselines(client); + + // CmdSceneReady sceneReady = new CmdSceneReady(); + // client.getSession().write(sceneReady.serialize()); + } }); diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 79ac9bee..434688a5 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -32,6 +32,7 @@ import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicLong; + import resources.common.*; import org.apache.mina.core.buffer.IoBuffer; @@ -47,7 +48,6 @@ import protocol.swg.HeartBeatMessage; import protocol.swg.ParametersMessage; import protocol.swg.SelectCharacter; import protocol.swg.UnkByteFlag; - import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.CrcStringTableVisitor; import engine.clientdata.visitors.WorldSnapshotVisitor; @@ -62,9 +62,7 @@ import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; - import main.NGECore; - import resources.objects.building.BuildingObject; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; @@ -72,6 +70,7 @@ import resources.objects.guild.GuildObject; import resources.objects.player.PlayerObject; import resources.objects.staticobject.StaticObject; import resources.objects.tangible.TangibleObject; +import resources.objects.waypoint.WaypointObject; import resources.objects.weapon.WeaponObject; @SuppressWarnings("unused") @@ -157,6 +156,8 @@ public class ObjectService implements INetworkDispatch { object = new GuildObject(core, objectID, planet, position, orientation, Template); + } else if(Template.startsWith("object/waypoint")) { + object = new WaypointObject(objectID, planet, position); } else { return null; @@ -355,11 +356,11 @@ public class ObjectService implements INetworkDispatch { client.setParent(creature); objectList.add(creature); + creature.viewChildren(creature, true, true, new Traverser() { @Override public void process(SWGObject object) { - //System.out.println(object.getTemplate()); objectList.add(object); } @@ -372,37 +373,46 @@ public class ObjectService implements INetworkDispatch { if(object.getParentId() != 0 && object.getContainer() == null) object.setParent(getObject(object.getParentId())); object.getContainerInfo(object.getTemplate()); + if(getObject(object.getObjectID()) == null) + objectList.add(object); } - }); + }); + if(creature.getParentId() != 0) { SWGObject parent = getObject(creature.getParentId()); parent._add(creature); } - Point3D position = creature.getWorldPosition(); + Point3D position = creature.getPosition(); - //UnkByteFlag unkByteFlag = new UnkByteFlag(); + UnkByteFlag unkByteFlag = new UnkByteFlag(); //session.write(unkByteFlag.serialize()); - //ParametersMessage parameters = new ParametersMessage(); + ParametersMessage parameters = new ParametersMessage(); //session.write(parameters.serialize()); - + + core.buffService.clearBuffs(creature); + core.chatService.loadMailHeaders(client); HeartBeatMessage heartBeat = new HeartBeatMessage(); session.write(heartBeat.serialize()); - CmdStartScene startScene = new CmdStartScene((byte) 0, objectId, creature.getPlanet().getPath(), creature.getTemplate(), position.x, position.y, position.z, System.currentTimeMillis() / 1000, creature.getRadians()); + CmdStartScene startScene = new CmdStartScene((byte) 0, objectId, creature.getPlanet().getPath(), creature.getTemplate(), position.x, position.y, position.z, System.currentTimeMillis() / 1000, 0); session.write(startScene.serialize()); - - core.simulationService.handleZoneIn(client); creature.makeAware(creature); - //CmdSceneReady cmdSceneReady = new CmdSceneReady(); - //session.write(cmdSceneReady.serialize()); + + creature.makeAware(core.guildService.getGuildObject()); + + core.simulationService.handleZoneIn(client); + + CmdSceneReady sceneReady = new CmdSceneReady(); + client.getSession().write(sceneReady.serialize()); + + core.playerService.postZoneIn(creature); - //core.simulationService.teleport(creature, new Point3D(position.x, core.terrainService.getHeight(creature.getPlanetId(), position.x, position.z), position.z), creature.getOrientation()); } }); @@ -423,13 +433,15 @@ public class ObjectService implements INetworkDispatch { if(obj != null) { obj.setisInSnapshot(true); obj.setParentId(chunk.parentId); + if(obj instanceof CellObject) { + ((CellObject) obj).setCellNumber(chunk.cellNumber); + } } //System.out.print("\rLoading Object [" + counter + "/" + visitor.getChunks().size() + "] : " + visitor.getName(chunk.nameId)); } visitor.dispose(); synchronized(objectList) { for(SWGObject obj : objectList) { - obj.getTemplateData().dispose(); if(obj.getParentId() != 0 && getObject(obj.getParentId()) != null) { SWGObject parent = getObject(obj.getParentId()); parent.add(obj); diff --git a/src/services/trade/TradeService.java b/src/services/trade/TradeService.java index c7a0b770..e1a7526e 100644 --- a/src/services/trade/TradeService.java +++ b/src/services/trade/TradeService.java @@ -205,6 +205,7 @@ public class TradeService implements INetworkDispatch{ System.out.println("Trading item: " + objectToTrade.getCustomName() + " detail: " + objectToTrade.getDetailFilename()); System.out.println("tradingObjectTable: " + tradingObjectsTable.toString()); + tradee.makeAware(objectToTrade); AddItemMessage tradeeResponse = new AddItemMessage(); tradeeResponse.setTradeObjectID(tradeItemID); tradee.getClient().getSession().write(tradeeResponse.serialize());