diff --git a/scripts/character_builder_terminal.py b/scripts/character_builder_terminal.py index 78901ad4..1b42bd5e 100644 --- a/scripts/character_builder_terminal.py +++ b/scripts/character_builder_terminal.py @@ -305,7 +305,7 @@ def miscHandler(owner): returnList = Vector() returnList.add('List.lstList:SelectedRow') window.addHandler(0, '', Trigger.TRIGGER_OK, returnList, miscHandlerCallback) - window.addListBoxMenuItem('Backpack', 0) + window.addListBoxMenuItem('Instrument', 0) window.addListBoxMenuItem('Heroism Jewelry Set', 1) window.addListBoxMenuItem('Belt of Master Bodo Baas', 2) window.addListBoxMenuItem('Starter Equipment Box', 3) @@ -321,7 +321,7 @@ def miscHandlerCallback(owner, window, eventType, returnList): return if returnList.get(0)=='0': - backpack(owner, inventory) + instrument(owner, inventory) return if returnList.get(0)=='1': heroismJewelry(owner, inventory) @@ -595,6 +595,7 @@ def compositeArmor(owner, inventory): comp_chest.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); comp_boots = core.objectService.createObject("object/tangible/wearables/armor/composite/shared_armor_composite_boots.iff", owner.getPlanet()) comp_gloves = core.objectService.createObject("object/tangible/wearables/armor/composite/shared_armor_composite_gloves.iff", owner.getPlanet()) + inventory.add(comp_bicep_r); inventory.add(comp_bicep_l); inventory.add(comp_bracer_r); @@ -610,60 +611,11 @@ def compositeArmor(owner, inventory): def clonetrooperArmor(owner, inventory): clonetrooper_bicep_r = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_bicep_r.iff", owner.getPlanet()) - clonetrooper_bicep_r.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_bicep_r.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_bicep_r.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_bicep_r.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_bicep_r.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_bicep_r.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - clonetrooper_bicep_l = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_bicep_l.iff", owner.getPlanet()) - clonetrooper_bicep_l.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_bicep_l.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_bicep_l.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_bicep_l.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_bicep_l.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_bicep_l.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - - clonetrooper_bracer_r = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_bracer_r.iff", owner.getPlanet()) - clonetrooper_bracer_r.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_bracer_r.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_bracer_r.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_bracer_r.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_bracer_r.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_bracer_r.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - clonetrooper_bracer_l = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_bracer_l.iff", owner.getPlanet()) - clonetrooper_bracer_l.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_bracer_l.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_bracer_l.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_bracer_l.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_bracer_l.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_bracer_l.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - clonetrooper_leggings = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_leggings.iff", owner.getPlanet()) - clonetrooper_leggings.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_leggings.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_leggings.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_leggings.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_leggings.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_leggings.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - clonetrooper_helmet = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_helmet.iff", owner.getPlanet()) - clonetrooper_helmet.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_helmet.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_helmet.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_helmet.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_helmet.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_helmet.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); - clonetrooper_chest = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_chest_plate.iff", owner.getPlanet()) - clonetrooper_chest.setIntAttribute("cat_armor_standard_protection.armor_eff_kinetic", 7000); - clonetrooper_chest.setIntAttribute("cat_armor_standard_protection.armor_eff_energy", 5000); - clonetrooper_chest.setIntAttribute("cat_armor_special_protection.special_protection_type_heat", 6000); - clonetrooper_chest.setIntAttribute("cat_armor_special_protection.special_protection_type_cold", 6000); - clonetrooper_chest.setIntAttribute("cat_armor_special_protection.special_protection_type_acid", 6000); - clonetrooper_chest.setIntAttribute("cat_armor_special_protection.special_protection_type_electricity", 6000); clonetrooper_boots = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_boots.iff", owner.getPlanet()) clonetrooper_gloves = core.objectService.createObject("object/tangible/wearables/armor/clone_trooper/shared_armor_clone_trooper_neutral_s01_gloves.iff", owner.getPlanet()) @@ -1347,8 +1299,8 @@ def jediBelt(owner, inventory): screenOne(core, owner) return -def backpack(owner, inventory): - # inventory.add(core.objectService.createObject("object/tangible/wearables/backpack/shared_backpack_s01.iff", owner.getPlanet())) +def instrument(owner, inventory): + inventory.add(core.objectService.createObject("object/tangible/instrument/shared_slitherhorn.iff", owner.getPlanet())) screenOne(core, owner) return diff --git a/scripts/commands/startdance.py b/scripts/commands/startdance.py index ce557827..b24f18df 100644 --- a/scripts/commands/startdance.py +++ b/scripts/commands/startdance.py @@ -56,7 +56,8 @@ def startDance(core, actor, danceName, visual): entSvc = core.entertainmentService if visual <= 0: - visual = entSvc.getDanceVisualId(danceName) + visual = entSvc.getDanceVisualId(danceName) + print("[PYTHON] startdance.visual = " , visual) if visual <= 0: actor.sendSystemMessage('@performance:dance_unknown_self',0) diff --git a/scripts/commands/startmusic.py b/scripts/commands/startmusic.py new file mode 100644 index 00000000..ff1a94e3 --- /dev/null +++ b/scripts/commands/startmusic.py @@ -0,0 +1,173 @@ +import sys +from services.sui import SUIWindow +from services.sui import SUIService +from services.sui.SUIWindow import Trigger +from services.sui.SUIService import ListBoxType +from java.util import Vector +from java.util import HashMap +from resources.datatables import Posture + +def setup(): + return + +def run(core, actor, target, commandString): + global suiWindow + global actorObject + global entSvc + actorObject = actor + entSvc = core.entertainmentService + + instrumentObj = entSvc.getInstrument(actor) + + #TODO: Determine if player has an instrument + if instrumentObj is not None: + #If player does have an instrument then determine what type of instrument the player has + instrumentStfName = instrumentObj.getStfName() + instrumentCode = -1 + #If type is traz then audioID is 1 + if instrumentStfName == "obj_traz_classic": + instrumentCode = 1 + #if type is slitherhorn then audioID is 2 + elif instrumentStfName == "obj_slitherhorn_classic": + instrumentCode = 2 + #if type is fanfar then audioID is 3 + elif instrumentStfName == "obj_fanfar_classic": + instrumentCode = 3 + #if type is flutedroopy then audioID is 4 + #FIXME: I don't know what this is yet, but I suspect it's "obj_chidinkalu_horn_classic" + + #if type is kloohorn then audioID is 5 + elif instrumentStfName == "obj_kloo_horn_classic": + instrumentCode = 5 + #if type is fizz then audioID is 6 + elif instrumentStfName == "obj_fizzz_classic": + instrumentCode = 6 + #if type is bandfill then audioID is 7 + elif instrumentStfName == "obj_bandfill_classic": + instrumentCode = 7 + + #if type is omnibox then audioID is 8 + #FIXME: This instrument isn't equipped when played + + #if type is nalargon then audioID is 9 + #FIXME: This instrument isn't equipped when played + + #if type is mandoviol then audioID is 10 + elif instrumentStfName == "obj_mandoviol_classic": + instrumentCode = 10 + #if type is xantha then audioID is 11 + elif instrumentStfName == "xantha_n": + instrumentCode = 11 + #if type is flangedjessoon then audioID is 12 + elif instrumentStfName == "obj_jessoon": + instrumentCode = 12 + #if type is valahorn then audioID is 13 + elif instrumentStfName == "obj_valahorn": + instrumentCode = 13 + #if type is downeybox then audioID is 14 + #FIXME: This instrument isn't equipped when played + + #TODO: Handle instruments that are placed on the ground + + print('instrumentCode: ' , instrumentCode) + if instrumentCode > 0: + #Parse command string + if len(commandString) > 0: + params = commandString.split(" ") + performance = entSvc.getPerformance(params[0], instrumentCode) + print('line number: ', performance.getLineNumber()) + if performance is None: + #Not a proper song + actor.sendSystemMessage('@performance:music_invalid_song', 0) + return + + #Handle lack of skill + if not entSvc.canPerform(actor, performance): + actor.sendSystemMessage('@performance:music_lack_skill_self',0) + return + startMusic(core, actor, performance.getLineNumber()) + else: + availableSongs = entSvc.getAvailableSongs(actor, instrumentCode) + + suiSvc = core.suiService + suiWindow = suiSvc.createListBox(ListBoxType.LIST_BOX_OK_CANCEL, "@performance:select_song", "@performance:available_songs", availableSongs, actor, None, 10) + + returnList = Vector() + returnList.add("List.lstList:SelectedRow") + suiWindow.addHandler(0, '', Trigger.TRIGGER_OK, returnList, handleStartMusic) + + suiSvc.openSUIWindow(suiWindow) + else: + #Equipped item is not an instrument + actor.sendSystemMessage('@performance:music_no_instrument', 0) + pass + else: + #No instrument equipped + actor.sendSystemMessage('@performance:music_no_instrument', 0) + pass + ''' + NOTE: animation files are "all_b_dnc_musician__loop.ans" + NOTE: flourish animation files are "all_b_dnc_musician__sp_8.ans" + This information doesn't seem to be needed... + ''' + pass + +def handleStartMusic(core, owner, eventType, returnList): + item = suiWindow.getMenuItems().get(int(returnList.get(0))) + print(item.getObjectId()) + startMusic(core, actorObject, item.getObjectId()) + pass + +def startMusic(core, actor, performanceLineNumber): + if actor.getPosture == 0x09: + actor.sendSystemMessage('@performance:already_performing_self', 0) + pass + + if not actor.getPerformanceWatchee(): + #this also notifies the client with a delta4 + actor.setPerformanceWatchee(actor) + actor.addSpectator(actor) + + actor.setPosture(0x09) + + #Turn on XP gain + playerObject = actor.getSlottedObject('ghost') + if playerObject and playerObject.getProfession() == "entertainer_1a" and actor.getLevel() != 90: + entSvc.startPerformanceExperience(actor) + + performance = entSvc.getPerformanceByIndex(performanceLineNumber)#TODO: Refactor to not need this + audioId = performance.getInstrumentAudioId() + + songAnim = "music_0" + if audioId < 7: + songAnim = "music_3" #Horns + elif audioId < 8: + songAnim = "music_1" #Bandfill + elif audioId < 9: + songAnim = "music_4" #Omnibox + elif audioId < 10: + songAnim = "music_2" #Nargalon + elif audioId < 12: + songAnim = "music_5" #String instruments + elif audioId < 14: + songAnim = "music_3" #More horns + elif audioId < 15: + songAnim = "music_4" #downeybox (Don't think this was ever added) + + print(songAnim) + + + actor.sendSystemMessage('@performance:music_start_self',0) + #entSvc.startPerformance(actor, performance.getLineNumber(), -842249156, "dance_0", 0)#TODO: Figure out what exactly goes in parameter slots 2 and 3 + #entSvc.startPerformance(actor, performance.getLineNumber(), -842249156, anim, 0)#TODO: Figure out what exactly goes in parameter slots 2 and 3 + entSvc.startPerformance(actor, performanceLineNumber+1, -842249156, songAnim, 0)#TODO: Figure out what exactly goes in parameter slots 2 and 3 + ''' + Bandfill = music_1 + Nargalon = music_2 + (Some flute-ish)[perhaps traz] = music_3 + Omnibox = music_4 + Mandoviol = music_5 + ''' + + pass + \ No newline at end of file diff --git a/scripts/commands/stopdance.py b/scripts/commands/stopdance.py index 1427496b..570441ae 100644 --- a/scripts/commands/stopdance.py +++ b/scripts/commands/stopdance.py @@ -11,5 +11,5 @@ def run(core, actor, target, commandString): actor.sendSystemMessage('@performance:dance_not_performing', 0) return - actor.stopPerformance() + entSvc.stopPerformance(actor) return diff --git a/scripts/commands/stopmusic.py b/scripts/commands/stopmusic.py new file mode 100644 index 00000000..84cc095f --- /dev/null +++ b/scripts/commands/stopmusic.py @@ -0,0 +1,16 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + entSvc = core.entertainmentService + perf = entSvc.getPerformanceByIndex(actor.getPerformanceId()) + + if actor.getPosture() != 0x09 or not perf or perf.getDanceVisualId() < 0: + actor.sendSystemMessage('@performance:music_not_performing', 0) + return + + entSvc.stopPerformance(actor) + #actor.sendSystemMessage('@performance:music_stop_self', 0) + return diff --git a/scripts/mobiles/dathomir/undead_deathtrooper.py b/scripts/mobiles/dathomir/undead_deathtrooper.py new file mode 100644 index 00000000..e3ff624f --- /dev/null +++ b/scripts/mobiles/dathomir/undead_deathtrooper.py @@ -0,0 +1,80 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_outbreak_undead_deathtrooper') ##TODO: Needs correct stf name + mobileTemplate.setLevel(5) + mobileTemplate.setDifficulty(Difficulty.NORMAL) + + mobileTemplate.setMinSpawnDistance(5) + mobileTemplate.setMaxSpawnDistance(10) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup('undead') + mobileTemplate.setAssistRange(15) + mobileTemplate.setRespawnTime(300) + mobileTemplate.setOptionsBitmask(Options.AGGRESSIVE | Options.ATTACKABLE) + + templates = Vector() + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_01_f.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_01_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_02_f.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_03_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_04_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_05_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_06_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_07_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_08_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_09_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_10_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_11_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_12_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_13_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_14_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_15_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_16_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_17_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_18_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_19_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_20_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_21_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_22_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_23_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_24_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_25_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_26_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_27_m.iff') + templates.add('object/mobile/shared_outbreak_undead_deathtrooper_28_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/rifle/shared_rifle_e11.iff', WeaponType.RIFLE, 0.8, 0, 'energy') + weaponTemplates.add(weapontemplate) + weapontemplate = WeaponTemplate('object/weapon/melee/unarmed/shared_unarmed_default.iff', WeaponType.ONEHANDEDMELEE, 1.0, 4, 'kinetic') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('RangedShot') + mobileTemplate.setDefaultAttack('MeleeHit') + mobileTemplate.setAttacks(attacks) + + lootPoolNames_1 = ['Junk'] + lootPoolChances_1 = [100] + lootGroupChance_1 = 65 + mobileTemplate.addToLootGroups(lootPoolNames_1,lootPoolChances_1,lootGroupChance_1) + + lootPoolNames_4 = ['random_stat_jewelry'] + lootPoolChances_4 = [100] + lootGroupChance_4 = 8 + mobileTemplate.addToLootGroups(lootPoolNames_4,lootPoolChances_4,lootGroupChance_4) + + core.spawnService.addMobileTemplate('undead_deathtrooper', mobileTemplate) + + return \ No newline at end of file diff --git a/scripts/mobiles/dynamicgroups/dathomir_quarantine_1.py b/scripts/mobiles/dynamicgroups/dathomir_quarantine_1.py new file mode 100644 index 00000000..12dc55c4 --- /dev/null +++ b/scripts/mobiles/dynamicgroups/dathomir_quarantine_1.py @@ -0,0 +1,16 @@ +import sys +from java.util import Vector +from services.spawn import DynamicSpawnGroup +from services.spawn import MobileTemplate + +def addDynamicGroup(core): + dynamicGroup = DynamicSpawnGroup() + mobileTemplates = Vector() + mobileTemplates.add('undead_deathtrooper') + dynamicGroup.setMobiles(mobileTemplates) + dynamicGroup.setGroupMembersNumber(5) + dynamicGroup.setName('dathomir_deathtroopers_1') + dynamicGroup.setMaxSpawns(-1) + dynamicGroup.setMinSpawnDistance(10) + core.spawnService.addDynamicGroup('dathomir_level_5_deathtroopers', dynamicGroup) + return diff --git a/scripts/mobiles/spawnareas/dathomir_quarantine.py b/scripts/mobiles/spawnareas/dathomir_quarantine.py new file mode 100644 index 00000000..5b8f0b6f --- /dev/null +++ b/scripts/mobiles/spawnareas/dathomir_quarantine.py @@ -0,0 +1,12 @@ +import sys +from java.util import Vector + +def addSpawnArea(core): + dynamicGroups = Vector() + dynamicGroups.add('dathomir_level_5_deathtroopers') + core.spawnService.addDynamicSpawnArea(dynamicGroups, -5700, -6500, 100, 'dathomir') + core.spawnService.addDynamicSpawnArea(dynamicGroups, -5640, -6550, 100, 'dathomir') + core.spawnService.addDynamicSpawnArea(dynamicGroups, -5850, -6400, 100, 'dathomir') + core.spawnService.addDynamicSpawnArea(dynamicGroups, -5800, -6500, 100, 'dathomir') + core.spawnService.addDynamicSpawnArea(dynamicGroups, -5600, -6525, 100, 'dathomir') + return diff --git a/scripts/mobiles/spawnareas/dathomir_quarantine_entrance.py b/scripts/mobiles/spawnareas/dathomir_quarantine_entrance.py deleted file mode 100644 index 3660d7b6..00000000 --- a/scripts/mobiles/spawnareas/dathomir_quarantine_entrance.py +++ /dev/null @@ -1,9 +0,0 @@ -# Spawn Area file created with PSWG Planetary Spawn Tool -import sys -from java.util import Vector - -def addSpawnArea(core): - dynamicGroups = Vector() - dynamicGroups.add('dark_jedi_wild_1') - core.spawnService.addDynamicSpawnArea(dynamicGroups, -5700, -6478, 100, 'dathomir') - return diff --git a/scripts/object/tangible/component/weapon/lightsaber/lightsaber_module_blackwing_crystal.py b/scripts/object/tangible/component/weapon/lightsaber/lightsaber_module_blackwing_crystal.py index ccad8904..77e03485 100644 --- a/scripts/object/tangible/component/weapon/lightsaber/lightsaber_module_blackwing_crystal.py +++ b/scripts/object/tangible/component/weapon/lightsaber/lightsaber_module_blackwing_crystal.py @@ -1,4 +1,9 @@ import sys def setup(core, object): - return \ No newline at end of file + object.setStringAttribute('condition', '100/100') + object.setStringAttribute('@obj_attr_n:color', 'Blackwing Bezoar') + object.setAttachment('radial_filename', 'item/tunable') + object.setStringAttribute('@obj_attr_n:crystal_owner", "\\#D1F56F UNTUNED \\#FFFFFF ') + return + \ No newline at end of file diff --git a/scripts/object/tangible/gcw/gcw_invasion_binoculars_01.py b/scripts/object/tangible/gcw/gcw_invasion_binoculars_01.py index 02df443d..ca6b996e 100644 --- a/scripts/object/tangible/gcw/gcw_invasion_binoculars_01.py +++ b/scripts/object/tangible/gcw/gcw_invasion_binoculars_01.py @@ -2,6 +2,7 @@ import sys def setup(core, object): object.setIntAttribute('no_trade', 1) + object.setIntAttribute('reuse_time', 5) object.setAttachment('radial_filename', 'object/usable') object.setStfFilename('static_item_n') object.setStfName('invasion_gcw_binoculars_01_01') diff --git a/scripts/static_spawns/dathomir/placeholder.txt b/scripts/static_spawns/dathomir/placeholder.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index b116f39b..be310f6f 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -368,6 +368,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { if (getPosture() == resources.datatables.Posture.SkillAnimating) { stopPerformance(); + //NGECore.getInstance().entertainmentService.stopPerformance(this);//FIXME: Maximum recursion. } if (getPosture() == posture) { @@ -1050,6 +1051,16 @@ public class CreatureObject extends TangibleObject implements IPersistent { this.entertainerExperience = entertainerExperience; } + public void cancelEntertainerExperience() + { + synchronized(objectMutex) { + if (entertainerExperience != null) { + entertainerExperience.cancel(true); + entertainerExperience = null; + } + } + } + public ScheduledFuture getInspirationTick() { return inspirationTick; } @@ -1106,6 +1117,11 @@ public class CreatureObject extends TangibleObject implements IPersistent { setListenToId((performanceListenee == null) ? 0L : performanceListenee.getObjectID()); } + public ArrayList getPerformanceAudience() + { + return new ArrayList(performanceAudience); + } + public int getFlourishCount() { synchronized(objectMutex) { return this.flourishCount; @@ -1588,7 +1604,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { } } - @Deprecated // FIXME Objects aren't meant for functionality + @Deprecated // FIXME Objects aren't meant for functionality. Instead use EntertainmentService.stopPerformance() public void stopPerformance() { setPerformanceId(0); setPerformanceCounter(0); @@ -1601,7 +1617,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { } } - sendSystemMessage("@performance:" + getPerformanceType() + "_stop_self", (byte)0); + //sendSystemMessage("@performance:" + getPerformanceType() + "_stop_self", (byte)0); stopAudience(); if (isPerforming()) { @@ -1609,7 +1625,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { } } - @Deprecated // FIXME Objects aren't meant for functionality + @Deprecated // FIXME Objects aren't meant for functionality. Instead use EntertainmentService.stopAudience() public void stopAudience() { synchronized(objectMutex) { if (performanceAudience == null) { diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 68907056..5a012745 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -1,9 +1,12 @@ package services; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -13,6 +16,7 @@ import java.util.concurrent.TimeUnit; import main.NGECore; +import org.apache.commons.collections.iterators.EntrySetMapIterator; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; @@ -49,10 +53,13 @@ public class EntertainmentService implements INetworkDispatch { private NGECore core; private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + private static final int SONG = 866729052; + private static final int DANCE = -1788534963; private Vector buffBuilderSkills = new Vector(); //FIXME: create a wrapper class for double key lookup maps - private ConcurrentHashMap performances = new ConcurrentHashMap(); + private ConcurrentHashMap performances = new ConcurrentHashMap(); private ConcurrentHashMap performancesByIndex = new ConcurrentHashMap(); private ConcurrentHashMap danceMap = new ConcurrentHashMap(); @@ -68,6 +75,9 @@ public class EntertainmentService implements INetworkDispatch { this.core = core; populateSkillCaps(); populatePerformanceTable(); + + System.out.printf("[DEBUG] number_of_performances: %d\n", performances.size()); + populatePerformanceEffects(); registerCommands(); loadCharacterCustomizationData(); @@ -437,13 +447,21 @@ public class EntertainmentService implements INetworkDispatch { if (p.getType() == -1788534963) { danceMap.put(new Integer(p.getDanceVisualId()), p); } - performances.put(p.getPerformanceName(), p); + performances.put(new PerformanceUID(p.getPerformanceName(), p.getInstrumentAudioId()), p); performancesByIndex.put(r, p); } } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } + + //TODO: Remove + Set debugSet = performances.keySet(); + for(PerformanceUID uid : debugSet) + { + System.out.println(uid.toString()); + } + } private void populateSkillCaps() { @@ -608,13 +626,15 @@ public class EntertainmentService implements INetworkDispatch { }*/ } + //FIXME: Refactor using new map --Complete-- public int getDanceVisualId(String danceName) { - Performance p = performances.get(danceName); + Performance p = getPerformance(danceName, 0); //if 0 , then it's no dance. need to handle that in the script. return ((p == null) ? 0 : p.getDanceVisualId()); } + //FIXME: Refactor using new map ?? Perhaps not ?? public Map getAvailableDances(CreatureObject actor) { Map dances = new HashMap(); @@ -627,6 +647,23 @@ public class EntertainmentService implements INetworkDispatch { } + public Map getAvailableSongs(CreatureObject actor, int instrumentCode) + { + Map songs = new HashMap(); + for(Performance performance : performances.values()) + { + if(performance.getInstrumentAudioId() == instrumentCode) + { + if(canPerform(actor, performance)) + { + songs.put(new Long(performance.getLineNumber()), performance.getPerformanceName()); + } + } + } + return songs; + } + + //FIXME: if visualId > 0 then it is a dance... public boolean isDance(int visualId) { return ( danceMap.get(visualId) != null ) ; } @@ -638,17 +675,31 @@ public class EntertainmentService implements INetworkDispatch { return false; } + public boolean canDance(CreatureObject actor, int visualId) { if (!isDance(visualId)) { return false; } return canDance(actor, danceMap.get(visualId)); } + + public boolean canPerform(CreatureObject actor, Performance performance) + { + if(performance.getRequiredInstrument() != null) + { + boolean hasInstrument = actor.hasAbility(performance.getRequiredInstrument()); + boolean hasSong = actor.hasAbility(performance.getRequiredSong()); + return hasInstrument && hasSong; + } + else return actor.hasAbility(performance.getRequiredDance()); + } public Performance getDance(int visualId) { return danceMap.get(visualId); } - public Performance getPerformance(String name) { - return performances.get(name); + //FIXME: Refactor using new map -COMPLETE- + //FIXME: Returning null for known combination... - fixed? + public Performance getPerformance(String name, int instrumentAudioId) { + return performances.get(new PerformanceUID(name, instrumentAudioId)); } public Performance getPerformanceByIndex(int index) { @@ -670,6 +721,27 @@ public class EntertainmentService implements INetworkDispatch { } } + public void stopPerformance(CreatureObject actor) + { + Performance performance = getPerformanceByIndex(actor.getPerformanceId()); + + actor.setPerformanceId(0); + actor.setPerformanceCounter(0); + actor.setCurrentAnimation("");//I think the animation should be some sort of idle animation. + + actor.cancelEntertainerExperience(); + + String performanceType = (performance.getType() == DANCE)? "dance" : "music"; + + actor.sendSystemMessage(String.format("@performance:%s_stop_self", performanceType), (byte)0);//FIXME: This hasn't been sending the correct message + stopAudience(actor); + + if (actor.isPerforming()) { + actor.setPerforming(false); + } + actor.setPosture((byte) 0x0); + } + public void startPerformanceExperience(final CreatureObject entertainer) { final ScheduledFuture experienceTask = scheduler.scheduleAtFixedRate(() -> { try { @@ -751,12 +823,56 @@ public class EntertainmentService implements INetworkDispatch { } + public void stopAudience(CreatureObject actor) + { + synchronized(actor.getMutex()) { + if (actor.getPerformanceAudience() == null) { + return; + } + + String performanceType = actor.getPerformanceType(); + Iterator it = actor.getPerformanceAudience().iterator(); + + while (it.hasNext()) { + CreatureObject next = it.next(); + + if (((performanceType.equals("dance")) && (next.getPerformanceWatchee() != actor)) + || ((performanceType.equals("music")) && (next.getPerformanceListenee() != actor))) { + continue; + } + + if (performanceType.equals("dance")) { + next.setPerformanceWatchee(null); + } else if (performanceType.equals("musci")) { + next.setPerformanceListenee(null); + } + + //this may be a bit dodgy. + boolean isEntertained = next.getPerformanceListenee() != null && next.getPerformanceWatchee() != null; + + if (!isEntertained) { + next.setMoodAnimation(""); + } + + if (next == actor) { + continue; + } + + + next.sendSystemMessage("@performance:" + performanceType + "_stop_other", (byte)0); + } + + actor.getPerformanceAudience().clear(); + //performanceAudience = new ArrayList(); + } + } public void performFlourish(final CreatureObject performer, int flourish) { // FIXME There wasn't a limit on flourishes; they just queued up. if (performer.getFlourishCount() > 0 || performer.isPerformingFlourish()) { performer.sendSystemMessage("@performance:flourish_wait_self", (byte) 0); return; } + //FIXME: I don't think this will work. Performance performance = getPerformanceByIndex(performer.getPerformanceId()); if(performance == null) @@ -987,9 +1103,70 @@ public class EntertainmentService implements INetworkDispatch { return 0; } + /** + * @param actor Player + * @return SWGObject equipped in the player's right hand + */ + public SWGObject getInstrument(CreatureObject actor) + { + return actor.getSlottedObject("hold_r"); + } + @Override public void shutdown() { } + + /** + * @author Glen + * This class serves as a unique id for performances. + * The performance.iff file is structured very similar to a database, and with that idea in mind + * this helper-class will serve as essentially the primary key of each performance. + */ + private class PerformanceUID + { + private final String performanceName; + private final int instrumentAudioId; + + public PerformanceUID(String performanceName, int instrumentAudioId) + { + this.performanceName = performanceName; + this.instrumentAudioId = instrumentAudioId; + } + + public boolean equals(PerformanceUID other) { + if(other != null) + { + if(this.performanceName == other.performanceName && this.instrumentAudioId == other.instrumentAudioId) + { + return true; + } + } + return false; + } + + @Override + public boolean equals(Object obj) { + if(obj != null && this.getClass() == obj.getClass() && this.performanceName.equals(((PerformanceUID)obj).performanceName) && this.instrumentAudioId == ((PerformanceUID)obj).instrumentAudioId) + { + return true; + } + return false; + } + + @Override + public int hashCode() { + return this.performanceName != null ? performanceName.hashCode() * 37 + instrumentAudioId: instrumentAudioId; +// int hash = performanceName.hashCode() ^ instrumentAudioId; +// return hash; + } + + @Override + public String toString() { + return "PerformanceUID [performanceName=" + performanceName + + ", instrumentAudioId=" + instrumentAudioId + ", hashCode = " + hashCode() + "]"; + } + + } } diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index ab0f4eae..857b54ac 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -1288,7 +1288,8 @@ public class ObjectService implements INetworkDispatch { if(! checkIfObjectAlreadyInList(object.getObjectID())) objectList.put(object.getObjectID(), object); } else { - Thread.currentThread().dumpStack(); + Thread.currentThread(); + Thread.dumpStack(); } }); @@ -1731,12 +1732,12 @@ public class ObjectService implements INetworkDispatch { } private void addCellsToBuildings(){ - Iterator it = null; + Iterator it = null; synchronized(buildingMap){ it = buildingMap.entrySet().iterator(); } while (it.hasNext()) { - Map.Entry pairs = (Map.Entry)it.next(); + Map.Entry pairs = (Map.Entry)it.next(); long buildingId = (long) pairs.getKey(); BuildingObject building = (BuildingObject)pairs.getValue(); //System.out.println("We have buildingId " +buildingId);