// ====================================================================== // performance.scriptlib - music/dancing script library // ====================================================================== include library.colors; include library.datatable; include library.utils; include library.sui; include library.combat; include library.camping; include library.city; include library.factions; include library.groundquests; include library.regions; include library.group; include library.pet_lib; include library.xp; include library.buff; include library.prose; include library.respec; include library.session; include library.beast_lib; // ====================================================================== const string DATATABLE_PERFORMANCE = "datatables/performance/performance.iff"; const string DATATABLE_COL_HEAL_WOUND = "healMindWound"; const string DATATABLE_COL_HEAL_SHOCK = "healShockWound"; const string DATATABLE_COL_LOOP_DURATION = "loopDuration"; const string DATATABLE_COL_ACTION_COST = "actionPointsPerLoop"; const string DATATABLE_COL_REQ_SKILL = "requiredSkillMod"; const string DATATABLE_COL_REQ_SKILL_VALUE = "requiredSkillModValue"; const string DATATABLE_COL_REQ_INSTRUMENT = "requiredInstrument"; const string DATATABLE_COL_REQ_SONG = "requiredSong"; const string DATATABLE_COL_REQ_DANCE = "requiredDance"; const string DATATABLE_COL_REQ_JUGGLE = "requiredJuggle"; const string DATATABLE_COL_BASE_XP = "baseXp"; const string DATATABLE_COL_FLOURISH_XP_MOD = "flourishXpMod"; const string DATATABLE_PERFORMANCE_EFFECT = "datatables/performance/perform_effect.iff"; const string DATATABLE_COL_EFFECT_PERFORM_TYPE = "performanceType"; const string DATATABLE_COL_EFFECT_REQ_SKILL = "requiredSkillMod"; const string DATATABLE_COL_EFFECT_REQ_SKILL_VAL = "requiredSkillModValue"; const string DATATABLE_COL_EFFECT_REQ_PERFORM = "requiredPerforming"; const string DATATABLE_COL_EFFECT_TARGET_TYPE = "targetType"; const string DATATABLE_COL_EFFECT_DURATION = "effectDuration"; const string DATATABLE_COL_EFFECT_ACTION_COST = "effectActionCost"; const string DATATABLE_INSTRUMENT = "datatables/tangible/instrument_datatable.iff"; const string DATATABLE_COL_INSTRUMENT_NAME = "serverTemplateName"; const string DATATABLE_COL_INSTRUMENT_ID = "instrumentAudioId"; const string DATATABLE_COL_VISIBLE_NAME = "visibleName"; const float PERFORMANCE_HEARTBEAT_TIME = 10.0f; const float PERFORMANCE_FLOURISH_ROUNDTIME = 0.0f; const float PERFORMANCE_EFFECT_ROUNDTIME = 2.0f; const float PERFORMANCE_HEAL_RANGE = 60.0f; const float PERFORMANCE_INSPIRE_RANGE = 20.0f; const float PERFORMANCE_XP_RANGE = 30.0f; const float PERFORMANCE_OUTRO_ROUNDTIME = 15.0f; const float PERFORMANCE_BAND_MEMBER_RANGE = 50.0f; //1/21/2005 Kirk: reduce min buff delay from 120sec to 60sec. const int MIN_BUFF_DELAY = 60; const float INSPIRATION_BUFF_SEGMENT = 600.0f; const float MAX_INSPIRATION_TIME = 10800.0f; // 3 hours in seconds const string BUFF_PERFORM_INSPIRATION = "perform_inspire_1"; const string MUSIC_HEARTBEAT_SCRIPT = "systems.skills.performance.active_music"; const string DANCE_HEARTBEAT_SCRIPT = "systems.skills.performance.active_dance"; const string JUGGLE_HEARTBEAT_SCRIPT = "systems.skills.performance.active_juggle"; const string PERFORMANCE_SELECT = "systems.skills.performance.select_performance"; const string POST_PERFORMANCE = "systems.skills.performance.post_performance"; const string PERFORMANCE_ENTERTAINED_SCRIPT = "systems.skills.performance.entertained"; const string PERFORMANCE_TYPE_DANCE = "perf_type_dance"; const string PERFORMANCE_TYPE_MUSIC = "perf_type_music"; const string PERFORMANCE_TYPE_JUGGLE = "perf_type_juggle"; const string NPC_ENTERTAINMENT_MESSAGE_START = "handleEntertainmentStart"; const string NPC_ENTERTAINMENT_MESSAGE_STOP = "handleEntertainmentStop"; const string NPC_ENTERTAINMENT_NO_ENTERTAIN = "ai.noClap"; const string VAR_PERFORM = "performance"; const string VAR_PERFORM_FLOURISH = "performance.flourish"; const string VAR_PERFORM_COVERCHARGE = "performance.covercharge"; const string VAR_PERFORM_NO_PAY = "performance.no_pay"; const string VAR_PERFORM_PAY_WAIT = "performance.pay_wait"; const string VAR_PERFORM_PAY_AGREE = "performance.pay_agree"; const string VAR_PERFORM_PAY_DISAGREE = "performance.pay_disagree"; const string VAR_PERFROM_ALREADY_PAID = "performance.already_paid"; const string VAR_PERFORM_INSPIRATION = "performance.inspiration"; const string VAR_PERFORM_EFFECT = "performance.effect"; const string VAR_PERFORM_OUTRO = "post_performance.outro"; const string VAR_PERFORM_SEQUENCE = "performance.sequence"; const string VAR_PERFORM_APPLAUSE_COUNT = "performance.applause_count"; const string VAR_PERFORM_FLOURISH_COUNT = "performance.flourish_count"; const string VAR_PERFORM_FLOURISH_TOTAL = "performance.flourish_total"; const string VAR_PERFORM_FLOURISH_XP = "performance.flourish_xp"; const string VAR_PERFORM_NO_BAND_FLOURISH = "setting.performance.no_band_flourish"; const string VAR_PERFORM_NO_GROUP_DANCE = "setting.performance.no_group_dance"; const string VAR_AVAILABLE_PERFORMANCES = "performance.available_performances"; const string VAR_SELECT_JUGGLE_CHANGE = "performance.change_juggle"; const string VAR_SELECT_DANCE_CHANGE = "performance.change_dance"; const string VAR_SELECT_MUSIC_CHANGE = "performance.change_music"; const string VAR_SELECT_MUSIC_BAND = "performance.band_command"; const string VAR_PERFORM_MOOD = "performance.old_mood"; const string VAR_PERFORM_BUFF_TARGET = "performance.buff_target"; const string VAR_HEALING_XP_WOUND = "performance.healing_xp.wound"; const string VAR_HEALING_XP_DAMAGE = "performance.healing_xp.damage"; const string VAR_HEALING_XP_BUFF = "performance.healing_xp.buff"; const string VAR_TROUPE = "performance.troupe"; const string VAR_CURRENT_DANCE = "performance.dance.current"; const string VAR_BUFF_LIST = "performance.buff.list"; const string VAR_BUFF_TARGET = "performance.buff.target"; const string VAR_BUFF_SUI = "performance.buff.pid"; const string VAR_BUFF_TYPE = "performance.buff.type"; const int PERFORM_XP_FLOURISH_MAX = 2; const int PERFORM_XP_GROUP_MAX = 8; const int PERFORM_XP_AUDIENCE_MAX_1 = 15; const int PERFORM_XP_AUDIENCE_MAX_2 = 35; const int PERFORM_XP_APPLAUSE_MAX = 5; const int PERFORM_XP_INSPIRATION = 10; const int CURE_CLONING_SICKNESS_XP = 50; const float PERFORM_XP_GROUP_MOD = 0.33f; const float INSPIRATION_BONUS = .10f; const string[] APPLAUSE_POSTIVE = { "applaud", "bang", "cheer", "clap", "congratulate", "encourage", "softclap", "tiphat" }; const string[] APPLAUSE_NEGATIVE = { "bored", "fidget", "frown", "gag", "groan", "hiss", "nausea", "puke", "raspberry", "shake", "wince", "zone" }; const string[] INSPIRATION_BUFF_ENTERTAINER = { "general_inspiration", "artisan_inspiration", "entertainer_inspiration" }; const string[] INSPIRATION_BUFF_DANCER = { "architect_inspiration", "chef_inspiration", "tailor_inspiration", "merchant_inspiration" }; const string[] INSPIRATION_BUFF_MUSICIAN = { "droidengineer_inspiration", "weaponsmith_inspiration", "shipwright_inspiration", "armorsmith_inspiration" }; const int PERFORMANCE_EFFECT_DAZZLE = 1; const int PERFORMANCE_EFFECT_DISTRACT = 2; const int PERFORMANCE_EFFECT_SPOT_LIGHT = 3; const int PERFORMANCE_EFFECT_COLOR_LIGHTS = 4; const int PERFORMANCE_EFFECT_SMOKE_BOMB = 5; const int PERFORMANCE_EFFECT_FIRE_JETS = 6; const int PERFORMANCE_EFFECT_VENTRILOQUISM = 7; const int PERFORMANCE_EFFECT_CENTER_STAGE = 8; const int PERFORMANCE_EFFECT_COLOR_SWIRL = 9; const int PERFORMANCE_EFFECT_DANCE_FLOOR = 10; const int PERFORMANCE_EFFECT_FEATURED_SOLO = 11; const int PERFORMANCE_EFFECT_FIRE_JETS2 = 12; const int PERFORMANCE_EFFECT_LASER_SHOW = 13; const int SPECIAL_FLOURISH_OUTRO = -1; const int SPECIAL_FLOURISH_PAUSE_MUSIC = 0; const int HOLOGRAM_COMMAND_START_SONG = 1; const int HOLOGRAM_COMMAND_CHANGE_SONG = 2; const int HOLOGRAM_COMMAND_STOP_SONG = 3; const int HOLOGRAM_COMMAND_START_DANCE = 4; const int HOLOGRAM_COMMAND_CHANGE_DANCE = 5; const int HOLOGRAM_COMMAND_STOP_DANCE = 6; // Entertainer Effects v1.0 const string EFFECT_SPOT_LIGHT_1 = "clienteffect/entertainer_spot_light_level_1.cef"; const string EFFECT_SPOT_LIGHT_2 = "clienteffect/entertainer_spot_light_level_2.cef"; const string EFFECT_SPOT_LIGHT_3 = "clienteffect/entertainer_spot_light_level_3.cef"; const string EFFECT_COLOR_LIGHTS_1 = "clienteffect/entertainer_color_lights_level_1.cef"; const string EFFECT_COLOR_LIGHTS_2 = "clienteffect/entertainer_color_lights_level_2.cef"; const string EFFECT_COLOR_LIGHTS_3 = "clienteffect/entertainer_color_lights_level_3.cef"; const string EFFECT_DAZZLE_1 = "clienteffect/entertainer_dazzle_level_1.cef"; const string EFFECT_DAZZLE_2 = "clienteffect/entertainer_dazzle_level_2.cef"; const string EFFECT_DAZZLE_3 = "clienteffect/entertainer_dazzle_level_3.cef"; const string EFFECT_DISTRACT_1 = "clienteffect/entertainer_distract_level_1.cef"; const string EFFECT_DISTRACT_2 = "clienteffect/entertainer_distract_level_2.cef"; const string EFFECT_DISTRACT_3 = "clienteffect/entertainer_distract_level_3.cef"; const string EFFECT_SMOKE_BOMB_1 = "clienteffect/entertainer_smoke_bomb_level_1.cef"; const string EFFECT_SMOKE_BOMB_2 = "clienteffect/entertainer_smoke_bomb_level_2.cef"; const string EFFECT_SMOKE_BOMB_3 = "clienteffect/entertainer_smoke_bomb_level_3.cef"; const string EFFECT_FIRE_JETS_1 = "clienteffect/entertainer_fire_jets_level_1.cef"; const string EFFECT_FIRE_JETS_2 = "clienteffect/entertainer_fire_jets_level_2.cef"; const string EFFECT_FIRE_JETS_3 = "clienteffect/entertainer_fire_jets_level_3.cef"; const string EFFECT_VENTRILOQUISM_1 = "clienteffect/entertainer_ventriloquism_level_1.cef"; const string EFFECT_VENTRILOQUISM_2 = "clienteffect/entertainer_ventriloquism_level_2.cef"; const string EFFECT_VENTRILOQUISM_3 = "clienteffect/entertainer_ventriloquism_level_3.cef"; // Entertainer Effects v2.0 const string EFFECT_CENTER_STAGE = "clienteffect/entertainer_center_stage.cef"; const string EFFECT_COLOR_SWIRL = "clienteffect/entertainer_color_swirl.cef"; const string EFFECT_DANCE_FLOOR = "clienteffect/entertainer_dance_floor.cef"; const string EFFECT_FEATURED_SOLO = "clienteffect/entertainer_featured_solo.cef"; const string EFFECT_FIRE_JETS2 = "clienteffect/entertainer_fire_jets2.cef"; const string EFFECT_LASER_SHOW = "clienteffect/entertainer_laser_show.cef"; // server side string table (radial_performance.stf) const string_id SID_RADIAL_PERFORMANCE_LISTEN = new string_id("radial_performance", "listen"); const string_id SID_RADIAL_PERFORMANCE_WATCH = new string_id("radial_performance", "watch"); const string_id SID_RADIAL_PERFORMANCE_LISTEN_STOP = new string_id("radial_performance", "listen_stop"); const string_id SID_RADIAL_PERFORMANCE_WATCH_STOP = new string_id("radial_performance", "watch_stop"); // client side string table (performance.stf) const string_id SID_ALREADY_PERFORMING_SELF = new string_id("performance", "already_performing_self"); const string_id SID_MUSIC_NO_INSTRUMENT = new string_id("performance", "music_no_instrument"); const string_id SID_MUSIC_HOLOGRAM_NO_INSTRUMENT = new string_id("performance", "music_hologram_no_instrument"); //const string_id SID_MUSIC_BAD_SONG_FOR_INSTRUMENT = new string_id("performance", "music_bad_song_for_instrument"); const string_id SID_MUSIC_INVALID_SONG = new string_id("performance", "music_invalid_song"); const string_id SID_MUSIC_START_SELF = new string_id("performance", "music_start_self"); const string_id SID_MUSIC_START_OTHER = new string_id("performance", "music_start_other"); const string_id SID_MUSIC_START_BAND_SELF = new string_id("performance", "music_start_band_self"); const string_id SID_MUSIC_START_BAND_MEMBERS = new string_id("performance", "music_start_band_members"); const string_id SID_MUSIC_START_BAND_OTHER = new string_id("performance", "music_start_band_other"); const string_id SID_MUSIC_JOIN_BAND_SELF = new string_id("performance", "music_join_band_self"); const string_id SID_MUSIC_JOIN_BAND_STOP = new string_id("performance", "music_join_band_stop"); const string_id SID_MUSIC_BAND_JOIN_SONG_SELF = new string_id("performance", "music_band_join_song_self"); const string_id SID_MUSIC_BAND_JOIN_SONG_MEMBERS = new string_id("performance", "music_band_join_song_members"); const string_id SID_MUSIC_STOP_SELF = new string_id("performance", "music_stop_self"); const string_id SID_MUSIC_STOP_OTHER = new string_id("performance", "music_stop_other"); const string_id SID_MUSIC_STOP_BAND_SELF = new string_id("performance", "music_stop_band_self"); const string_id SID_MUSIC_STOP_BAND_MEMBERS = new string_id("performance", "music_stop_band_members"); const string_id SID_MUSIC_STOP_BAND_OTHER = new string_id("performance", "music_stop_band_other"); const string_id SID_MUSIC_PREPARE_STOP_SELF = new string_id("performance", "music_prepare_stop_self"); const string_id SID_MUSIC_PREPARE_STOP_BAND_SELF = new string_id("performance", "music_prepare_stop_band_self"); const string_id SID_MUSIC_PREPARE_STOP_BAND_MEMBERS = new string_id("performance", "music_prepare_stop_band_members"); const string_id SID_MUSIC_LISTEN_SELF = new string_id("performance", "music_listen_self"); const string_id SID_MUSIC_LISTEN_STOP_SELF = new string_id("performance", "music_listen_stop_self"); const string_id SID_MUSIC_LISTEN_PLAYING_SELF = new string_id("performance", "music_listen_playing_self"); const string_id SID_MUSIC_LISTEN_NOT_PLAYING = new string_id("performance", "music_listen_not_playing"); const string_id SID_MUSIC_LISTEN_OUT_OF_RANGE = new string_id("performance", "music_listen_out_of_range"); const string_id SID_MUSIC_LISTEN_NPC = new string_id("performance", "music_listen_npc"); const string_id SID_MUSIC_STILL_PLAYING = new string_id("performance", "music_still_playing"); const string_id SID_MUSIC_NOT_MUSICIAN = new string_id("performance", "music_not_musician"); const string_id SID_MUSIC_NOT_PERFORMING = new string_id("performance", "music_not_performing"); const string_id SID_MUSIC_MUST_BE_PERFORMING_SELF = new string_id("performance", "music_must_be_performing_self"); const string_id SID_MUSIC_LACK_SKILL_INSTRUMENT = new string_id("performance", "music_lack_skill_instrument"); const string_id SID_MUSIC_LACK_SKILL_SONG_SELF = new string_id("performance", "music_lack_skill_song_self"); const string_id SID_MUSIC_LACK_SKILL_SONG_BAND = new string_id("performance", "music_lack_skill_song_band"); const string_id SID_MUSIC_LACK_SKILL_BAND_MEMBER = new string_id("performance", "music_lack_skill_band_member"); const string_id SID_MUSIC_MUST_MATCH_BAND = new string_id("performance", "music_must_match_band"); const string_id SID_MUSIC_FAIL = new string_id("performance", "music_fail"); const string_id SID_MUSIC_OUTRO_WAIT = new string_id("performance", "music_outro_wait"); const string_id SID_MUSIC_TOO_TIRED = new string_id("performance", "music_too_tired"); const string_id SID_MUSIC_NO_MUSIC_PARAM = new string_id("performance", "music_no_music_param"); const string_id SID_MUSIC_TRACK_NOT_AVAILABLE = new string_id("performance", "music_track_not_available"); const string_id SID_MUSIC_OUT_OF_POWER = new string_id("performance", "music_out_of_power"); const string_id SID_DANCE_START_SELF = new string_id("performance", "dance_start_self"); const string_id SID_DANCE_START_OTHER = new string_id("performance", "dance_start_other"); const string_id SID_DANCE_STOP_SELF = new string_id("performance", "dance_stop_self"); const string_id SID_DANCE_STOP_OTHER = new string_id("performance", "dance_stop_other"); const string_id SID_DANCE_WATCH_SELF = new string_id("performance", "dance_watch_self"); const string_id SID_DANCE_WATCH_STOP_SELF = new string_id("performance", "dance_watch_stop_self"); const string_id SID_DANCE_WATCH_NOT_DANCING = new string_id("performance", "dance_watch_not_dancing"); const string_id SID_DANCE_WATCH_OUT_OF_RANGE = new string_id("performance", "dance_watch_out_of_range"); const string_id SID_DANCE_WATCH_NPC = new string_id("performance", "dance_watch_npc"); const string_id SID_DANCE_MUST_BE_PERFORMING_SELF = new string_id("performance", "dance_must_be_performing_self"); const string_id SID_DANCE_NOT_PERFORMING = new string_id("performance", "dance_not_performing"); const string_id SID_DANCE_UNKNOWN_SELF = new string_id("performance", "dance_unknown_self"); const string_id SID_DANCE_LACK_SKILL_SELF = new string_id("performance", "dance_lack_skill_self"); const string_id SID_DANCE_NOT_DANCER = new string_id("performance", "dance_not_dancer"); const string_id SID_DANCE_TOO_TIRED = new string_id("performance", "dance_too_tired"); const string_id SID_DANCE_NO_DANCE_PARAM = new string_id("performance", "dance_no_dance_param"); const string_id SID_DANCE_FAIL = new string_id("performance", "dance_fail"); const string_id SID_DANCE_LACK_SKILL_BAND = new string_id("performance", "dance_lack_skill_band"); const string_id SID_DANCE_LACK_SKILL_BAND_MEMBER = new string_id("performance", "dance_lack_skill_band_member"); const string_id SID_GROUP_DANCE_OFF = new string_id("performance", "dance_group_off"); const string_id SID_GROUP_DANCE_ON = new string_id("performance", "dance_group_on"); const string_id SID_JUGGLE_START_SELF = new string_id("performance", "juggle_start_self"); const string_id SID_JUGGLE_START_OTHER = new string_id("performance", "juggle_start_other"); const string_id SID_JUGGLE_STOP_SELF = new string_id("performance", "juggle_stop_self"); const string_id SID_JUGGLE_STOP_OTHER = new string_id("performance", "juggle_stop_other"); const string_id SID_JUGGLE_WATCH_SELF = new string_id("performance", "juggle_watch_self"); const string_id SID_JUGGLE_WATCH_STOP_SELF = new string_id("performance", "juggle_watch_stop_self"); const string_id SID_JUGGLE_WATCH_NOT_DANCING = new string_id("performance", "juggle_watch_not_juggling"); const string_id SID_JUGGLE_WATCH_OUT_OF_RANGE = new string_id("performance", "juggle_watch_out_of_range"); const string_id SID_JUGGLE_WATCH_NPC = new string_id("performance", "juggle_watch_npc"); const string_id SID_JUGGLE_MUST_BE_PERFORMING_SELF = new string_id("performance", "juggle_must_be_performing_self"); const string_id SID_JUGGLE_NOT_PERFORMING = new string_id("performance", "juggle_not_performing"); const string_id SID_JUGGLE_UNKNOWN_SELF = new string_id("performance", "juggle_unknown_self"); const string_id SID_JUGGLE_LACK_SKILL_SELF = new string_id("performance", "juggle_lack_skill_self"); const string_id SID_JUGGLE_NOT_JUGGLER = new string_id("performance", "juggle_not_juggler"); const string_id SID_JUGGLE_TOO_TIRED = new string_id("performance", "juggle_too_tired"); const string_id SID_JUGGLE_NO_JUGGLE_PARAM = new string_id("performance", "juggle_no_juggle_param"); const string_id SID_JUGGLE_FAIL = new string_id("performance", "juggle_fail"); const string_id SID_FLOURISH_WAIT_SELF = new string_id("performance", "flourish_wait_self"); const string_id SID_FLOURISH_PERFORM = new string_id("performance", "flourish_perform"); const string_id SID_FLOURISH_PERFORM_BAND_SELF = new string_id("performance", "flourish_perform_band_self"); const string_id SID_FLOURISH_PERFORM_BAND_MEMBER = new string_id("performance", "flourish_perform_band_member"); const string_id SID_FLOURISH_FORMAT = new string_id("performance", "flourish_format"); const string_id SID_BAND_FLOURISH_FORMAT = new string_id("performance", "band_flourish_format"); const string_id SID_BAND_SOLO_FORMAT = new string_id("performance", "band_solo_format"); const string_id SID_BAND_PAUSE_FORMAT = new string_id("performance", "band_pause_format"); const string_id SID_BAND_FLOURISH_ON = new string_id("performance", "band_flourish_on"); const string_id SID_BAND_FLOURISH_OFF = new string_id("performance", "band_flourish_off"); const string_id SID_BAND_FLOURISH_STATUS_ON = new string_id("performance", "band_flourish_status_on"); const string_id SID_BAND_FLOURISH_STATUS_OFF = new string_id("performance", "band_flourish_status_off"); const string_id SID_FLOURISH_NOT_PERFORMING = new string_id("performance", "flourish_not_performing"); const string_id SID_FLOURISH_NOT_VALID = new string_id("performance", "flourish_not_valid"); const string_id SID_FLOURISH_TOO_TIRED = new string_id("performance", "flourish_too_tired"); const string_id SID_FLOURISH_INSTRUMENT_UNKNOWN = new string_id("performance", "flourish_instrument_unknown"); const string_id SID_EFFECT_WAIT_SELF = new string_id("performance", "effect_wait_self"); const string_id SID_EFFECT_NOT_PERFORMING = new string_id("performance", "effect_not_performing"); const string_id SID_EFFECT_NOT_PERFORMING_CORRECT = new string_id("performance", "effect_not_performing_correct"); const string_id SID_EFFECT_LACK_SKILL_SELF = new string_id("performance", "effect_lack_skill_self"); const string_id SID_EFFECT_TOO_TIRED = new string_id("performance", "effect_too_tired"); const string_id SID_EFFECT_NEED_TARGET = new string_id("performance", "effect_need_target"); const string_id SID_EFFECT_LEVEL_TOO_HIGH = new string_id("performance", "effect_level_too_high"); const string_id SID_EFFECT_PERFORM_SPOT_LIGHT = new string_id("performance", "effect_perform_spot_light"); const string_id SID_EFFECT_PERFORM_COLOR_LIGHTS = new string_id("performance", "effect_perform_color_lights"); const string_id SID_EFFECT_PERFORM_DAZZLE = new string_id("performance", "effect_perform_dazzle"); const string_id SID_EFFECT_PERFORM_DISTRACT = new string_id("performance", "effect_perform_distract"); const string_id SID_EFFECT_PERFORM_SMOKE_BOMB = new string_id("performance", "effect_perform_smoke_bomb"); const string_id SID_EFFECT_PERFORM_FIRE_JETS = new string_id("performance", "effect_perform_fire_jets"); const string_id SID_EFFECT_PERFORM_VENTRILOQUISM = new string_id("performance", "effect_perform_ventriloquism"); const string_id SID_EFFECT_PERFORM_CENTER_STAGE = new string_id("performance", "effect_perform_center_stage"); const string_id SID_EFFECT_PERFORM_COLOR_SWIRL = new string_id("performance", "effect_perform_color_swirl"); const string_id SID_EFFECT_PERFORM_DANCE_FLOOR = new string_id("performance", "effect_perform_dance_floor"); const string_id SID_EFFECT_PERFORM_FEATURED_SOLO = new string_id("performance", "effect_perform_featured_solo"); const string_id SID_EFFECT_PERFORM_FIRE_JETS_2 = new string_id("performance", "effect_perform_fire_jets_2"); const string_id SID_EFFECT_PERFORM_LASER_SHOW = new string_id("performance", "effect_perform_laser_show"); const string_id SID_BUFF_SET_TARGET_SELF = new string_id("performance", "buff_set_target_self"); const string_id SID_BUFF_SET_TARGET_OTHER = new string_id("performance", "buff_set_target_other"); const string_id SID_BUFF_INVALID_TARGET_SELF = new string_id("performance", "buff_invalid_target_self"); const string_id SID_DENY_SERVICE_ADD_SELF = new string_id("performance", "deny_service_add_self"); const string_id SID_DENY_SERVICE_ADD_OTHER = new string_id("performance", "deny_service_add_other"); const string_id SID_DENY_SERVICE_REMOVE_SELF = new string_id("performance", "deny_service_remove_self"); const string_id SID_DENY_SERVICE_REMOVE_OTHER = new string_id("performance", "deny_service_remove_other"); const string_id SID_DENY_SERVICE_COVER_CHARGE = new string_id("performance", "deny_service_cover_charge"); const string_id SID_INSPIRE_MAX = new string_id("performance", "perform_inspire_max"); const string_id SID_INSPIRE_BUILDING = new string_id("performance", "perform_inspire_building"); const string_id SID_CC_START_CHARGE = new string_id("performance", "cc_start_charge"); const string_id SID_CC_STOP_CHARGE = new string_id("performance", "cc_stop_charge"); const string_id SID_CC_NO_FUNDS = new string_id("performance", "cc_no_funds"); const string_id SID_CC_NO_SKILL = new string_id("performance", "cc_no_skill"); const string_id SID_PERFORM_CC_QUERY1 = new string_id("performance", "cc_query1"); const string_id SID_PERFORM_CC_QUERY2 = new string_id("performance", "cc_query2"); const string_id SID_PERFORM_CC_QUERY_TITLE = new string_id("performance", "cc_query_t"); const string_id BUFF_TIME_FAILED = new string_id("performance", "buff_time_failed"); const string_id SHAPECHANGE = new string_id("spam","not_while_shapechanged"); // ====================================================================== void stopInspiration(obj_id actor) { int inspireBuffCrc = buff.getBuffOnTargetFromGroup(actor, "inspiration"); // if(inspireBuffCrc != 0) // buff.removeBuff(actor, inspireBuffCrc); // No inspiration type defined, no buff // if (!utils.hasScriptVar(actor, VAR_BUFF_TYPE)) // return; float buff_time = utils.getFloatScriptVar(actor, VAR_PERFORM_INSPIRATION); // string buff_type = utils.getStringScriptVar(actor, VAR_BUFF_TYPE); utils.removeScriptVar(actor, VAR_BUFF_TYPE); // buff.applyBuff(actor, buff_type, buff_time); if(utils.hasScriptVar(actor, "performance.inspireMaxReached")) utils.removeScriptVar(actor, "performance.inspireMaxReached"); } void stopListen(obj_id actor) { obj_id watchTarget = getPerformanceWatchTarget(actor); obj_id listenTarget = getPerformanceListenTarget(actor); stopListeningToMessage(listenTarget, "handlePerformerStartPerforming"); stopListeningToMessage(listenTarget, "handlePerformerStopPerforming"); removeTriggerVolume("performance_listen_volume"); if (!isIdValid(watchTarget)) detachScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT); setPerformanceListenTarget(actor, obj_id.NULL_ID); checkPlayerEntertained(actor, "dancer"); if (utils.hasScriptVar(actor, VAR_PERFORM_INSPIRATION)) stopInspiration(actor); if(!utils.hasScriptVar(actor, VAR_PERFROM_ALREADY_PAID)) { int charge = utils.getIntScriptVar(actor, performance.VAR_PERFORM_PAY_AGREE); money.systemPayout(money.ACCT_PERFORM_ESCROW, listenTarget, charge, "handlePayment", null); } utils.removeScriptVar(actor, VAR_PERFORM_PAY_AGREE); utils.removeScriptVar(actor, VAR_PERFORM_PAY_WAIT); utils.removeScriptVar(actor, VAR_PERFORM_PAY_DISAGREE); utils.removeScriptVar(actor, VAR_PERFROM_ALREADY_PAID); utils.removeScriptVar(actor, VAR_PERFORM_INSPIRATION); /* // Apply mind buffs if applicable. if(utils.hasScriptVar(actor, "performance.musicBuffTimer")) { int curTime = getGameTime(); int buffTime = utils.getIntScriptVar(actor, "performance.musicBuffTimer"); if (curTime < buffTime + MIN_BUFF_DELAY) { utils.removeScriptVar(actor, "performance.musicBuffTimer"); sendSystemMessage(actor, BUFF_TIME_FAILED); } else { utils.removeScriptVar(actor, "performance.musicBuffTimer"); obj_id objBuffTarget = utils.getObjIdScriptVar(listenTarget, VAR_PERFORM_BUFF_TARGET); if ((group.inSameGroup(listenTarget, actor) || (objBuffTarget == actor))) { //healing.activatePerformanceMindBuff(actor, PERFORMANCE_TYPE_MUSIC); if(objBuffTarget==actor) { utils.removeScriptVar(watchTarget, VAR_PERFORM_BUFF_TARGET); } } } } */ } void listen(obj_id actor, obj_id target) { session.logActivity(actor, session.ACTIVITY_BEEN_ENTERTAINED); obj_id musician = getPerformanceListenTarget(actor); LOG ("performance_listen", "Current listen target is " + musician); if (isIdValid(musician)) { stopListen(actor); } if (!isIdValid(target)) // stop listening { performanceMessageToSelf(actor, null, SID_MUSIC_LISTEN_STOP_SELF); stopListen(actor); return; } if (!isPlayer(target)) { performanceMessageToSelf(actor, null, SID_MUSIC_LISTEN_NPC); return; } if (!hasScript(target, MUSIC_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, target, SID_MUSIC_LISTEN_NOT_PLAYING); return; } if (utils.hasScriptVar(target, performance.VAR_PERFORM_COVERCHARGE)) { if(checkDenyService(target, actor)) { sendSystemMessage(actor, new string_id("performance", "deny_cant_pay_cover")); utils.setScriptVar(actor, performance.VAR_PERFORM_PAY_WAIT, 0); } else { int charge = utils.getIntScriptVar(target, performance.VAR_PERFORM_COVERCHARGE); utils.setScriptVar(actor, performance.VAR_PERFORM_PAY_WAIT, charge); string title = "@performance:cc_query_t"; string prompt = "@performance:cc_query1"; prompt += " " + charge + " "; prompt += "@performance:cc_query2"; sui.msgbox(target, actor, prompt, sui.YES_NO, title, "HandleCoverCharge"); //setting scriptvar so the musician can get a coverCharge message when paid. utils.setScriptVar(actor, "dancerID", target); } } setPerformanceListenTarget(actor, target); if (actor != target) { listenToMessage(target, "handlePerformerStopPerforming"); //LOG ("performance_listen", "Creating trigger volume."); createTriggerVolume("performance_listen_volume", PERFORMANCE_HEAL_RANGE, true); //LOG ("performance_listen", "Adding trigger volume event source."); addTriggerVolumeEventSource("performance_listen_volume", target); //LOG ("performance_listen", "Checking trigger volume contents."); //obj_id[] contents = getTriggerVolumeContents(actor, "performance_listen_volume"); //LOG ("performance_listen", "Trigger volume contents = "+contents.length); startEntertainingPlayer(actor); utils.setScriptVar(actor, "performance.musicBuffTimer", getGameTime()); if (!hasScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT)) attachScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT); if (hasScript(target, "quest.crowd_pleaser.player_popularity") ) { dictionary popularity = new dictionary(); popularity.put("player", actor); messageTo(target, "handleEntertainedPlayer", popularity, 1, false); } if ( hasScript(target, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("listener", actor); messageTo(target, "handleNewPlayerEntertainerAction", webster, 1, false); obj_id[] bandMembers = getBandMembers(target); if ( bandMembers != null && bandMembers.length > 0 ) { for ( int i = 0; i < bandMembers.length; i++ ) { obj_id bandMate = bandMembers[i]; if ( isIdValid(bandMate) ) { messageTo(bandMate, "handleNewPlayerEntertainerAction", webster, 1, false); } } } } } if (!utils.hasScriptVar(target, performance.VAR_PERFORM_COVERCHARGE)) { performanceMessageToSelf(actor, target, SID_MUSIC_LISTEN_SELF); } } // ---------------------------------------------------------------------- void stopWatch(obj_id actor) { obj_id watchTarget = getPerformanceWatchTarget(actor); obj_id listenTarget = getPerformanceListenTarget(actor); stopListeningToMessage(watchTarget, "handlePerformerStartPerforming"); stopListeningToMessage(watchTarget, "handlePerformerStopPerforming"); removeTriggerVolume("performance_watch_volume"); if (!isIdValid(listenTarget)) detachScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT); setPerformanceWatchTarget(actor, obj_id.NULL_ID); checkPlayerEntertained(actor, "musician"); if (utils.hasScriptVar(actor, VAR_PERFORM_INSPIRATION)) stopInspiration(actor); if(!utils.hasScriptVar(actor, VAR_PERFROM_ALREADY_PAID)) { int charge = utils.getIntScriptVar(actor, performance.VAR_PERFORM_PAY_AGREE); money.systemPayout(money.ACCT_PERFORM_ESCROW, watchTarget, charge, "handlePayment", null); } utils.removeScriptVar(actor, VAR_PERFORM_PAY_AGREE); utils.removeScriptVar(actor, VAR_PERFORM_PAY_WAIT); utils.removeScriptVar(actor, VAR_PERFORM_PAY_DISAGREE); utils.removeScriptVar(actor, VAR_PERFROM_ALREADY_PAID); utils.removeScriptVar(actor, VAR_PERFORM_INSPIRATION); /* // Apply mind buffs if applicable. if(utils.hasScriptVar(actor, "performance.dancerBuffTimer")) { int curTime = getGameTime(); int buffTime = utils.getIntScriptVar(actor, "performance.dancerBuffTimer"); if (curTime < buffTime + MIN_BUFF_DELAY) { utils.removeScriptVar(actor, "performance.dancerBuffTimer"); sendSystemMessage(actor, BUFF_TIME_FAILED); } else { utils.removeScriptVar(actor, "performance.dancerBuffTimer"); obj_id objBuffTarget = utils.getObjIdScriptVar(watchTarget, VAR_PERFORM_BUFF_TARGET); if ((group.inSameGroup(watchTarget, actor) || (objBuffTarget == actor))) { healing.activatePerformanceMindBuff(actor, PERFORMANCE_TYPE_DANCE); if(objBuffTarget==actor) { utils.removeScriptVar(watchTarget, VAR_PERFORM_BUFF_TARGET); } } } } */ } void watch(obj_id actor, obj_id target) { session.logActivity(actor, session.ACTIVITY_BEEN_ENTERTAINED); obj_id dancer = getPerformanceWatchTarget(actor); if (isIdValid(dancer)) { stopWatch(actor); } if (!isIdValid(target)) // stop watching { performanceMessageToSelf(actor, null, SID_DANCE_WATCH_STOP_SELF); stopWatch(actor); return; } if (!isPlayer(target)) { performanceMessageToSelf(actor, null, SID_DANCE_WATCH_NPC); return; } // Check to see if the target is performing if (!hasScript(target, DANCE_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, target, SID_DANCE_WATCH_NOT_DANCING); return; } if (utils.hasScriptVar(target, performance.VAR_PERFORM_COVERCHARGE)) { if(checkDenyService(target, actor)) { sendSystemMessage(actor, new string_id("performance", "deny_cant_pay_cover")); utils.setScriptVar(actor, performance.VAR_PERFORM_PAY_WAIT, 0); } else { int charge = utils.getIntScriptVar(target, performance.VAR_PERFORM_COVERCHARGE); utils.setScriptVar(actor, performance.VAR_PERFORM_PAY_WAIT, charge); string title = "@performance:cc_query_t"; string prompt = "@performance:cc_query1"; prompt += " " + charge + " "; prompt += "@performance:cc_query2"; sui.msgbox(target, actor, prompt, sui.YES_NO, title, "HandleCoverCharge"); //setting scriptvar so the dancer can get a coverCharge message when paid. utils.setScriptVar(actor, "dancerID", target); } } setPerformanceWatchTarget(actor, target); listenToMessage(target, "handlePerformerStopPerforming"); //LOG ("performance_watch", "Creating trigger volume."); createTriggerVolume("performance_watch_volume", PERFORMANCE_HEAL_RANGE, true); //LOG ("performance_watch", "Adding trigger volume event source."); addTriggerVolumeEventSource("performance_watch_volume", target); //LOG ("performance_watch", "Checking trigger volume contents."); //obj_id[] contents = getTriggerVolumeContents(actor, "performance_watch_volume"); //LOG ("performance_watch", "Trigger volume contents = "+contents.length); startEntertainingPlayer(actor); utils.setScriptVar(actor, "performance.dancerBuffTimer", getGameTime()); if (!hasScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT)) attachScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT); if ( hasScript(target, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("watcher", actor); messageTo(target, "handleNewPlayerEntertainerAction", webster, 1, false); } if (hasScript(target, "quest.crowd_pleaser.player_popularity") ) { dictionary popularity = new dictionary(); popularity.put("player", actor); messageTo(target, "handleEntertainedPlayer", popularity, 1, false); } if (!utils.hasScriptVar(target, performance.VAR_PERFORM_COVERCHARGE)) { performanceMessageToSelf(actor, target, SID_DANCE_WATCH_SELF); } } // ---------------------------------------------------------------------- void covercharge(obj_id actor, int amount) { if (!hasCommand(actor, "covercharge")) { performanceMessageToSelf(actor, null, SID_CC_NO_SKILL); return; } utils.setScriptVar(actor, VAR_PERFORM_COVERCHARGE, amount); prose_package pp = new prose_package(); pp = prose.setStringId(pp, SID_CC_START_CHARGE); pp = prose.setDI(pp, amount); sendSystemMessageProse(actor, pp); return; } // ---------------------------------------------------------------------- void startEntertainingPlayer(obj_id actor) { //setObjVar(actor, VAR_PERFORM_MOOD, getAnimationMood(actor)); setAnimationMood(actor, "entertained"); //Checking if player has a pet out to see if that pet enjoys watching an entertainer. if (beast_lib.getBeastOnPlayer(actor) != null) { obj_id beast = beast_lib.getBeastOnPlayer(actor); obj_id beastBCD = beast_lib.getBeastBCD(beast); messageTo (beastBCD, "ownerEntertained", null, 1, false); } } // ---------------------------------------------------------------------- void stopEntertainingPlayer(obj_id actor) { //string mood = getStringObjVar(actor, VAR_PERFORM_MOOD); setAnimationMood(actor, "default"); //removeObjVar(actor, VAR_PERFORM_MOOD); detachScript(actor, PERFORMANCE_ENTERTAINED_SCRIPT); } // ---------------------------------------------------------------------- boolean checkPlayerEntertained(obj_id actor, string performanceCheck) { LOG ("performance_entertained", "Checking to see if still being entertained"); boolean entertained = false; if (performanceCheck.equals("dancer") || performanceCheck.equals("both")) { obj_id dancer = getPerformanceWatchTarget(actor); if (isIdValid(dancer)) { if (getDistance(actor, dancer) < PERFORMANCE_HEAL_RANGE) { if (getPerformanceType(dancer) != 0) { LOG ("performance_entertained", "Still watching a dancer, still entertained"); entertained = true; } } else { performance.performanceMessageToSelf(actor, dancer, performance.SID_DANCE_WATCH_OUT_OF_RANGE); performance.stopWatch(actor); } } } if (performanceCheck.equals("musician") || performanceCheck.equals("both")) { obj_id musician = getPerformanceListenTarget(actor); if (isIdValid(musician)) { if (getDistance(actor, musician) < PERFORMANCE_HEAL_RANGE) { if (getPerformanceType(musician) != 0) { LOG ("performance_entertained", "Still listening to a musician, still entertained"); entertained = true; } } else { performance.performanceMessageToSelf(actor, musician, performance.SID_MUSIC_LISTEN_OUT_OF_RANGE); performance.stopListen(actor); } } } if (!entertained) { LOG ("performance_entertained", "No performances, leaving entertained mood"); stopEntertainingPlayer(actor); } return entertained; } // ---------------------------------------------------------------------- int lookupPerformanceIndex(int typeHash, string performanceName, int instrumentNumber) { string lowerPerformanceName = toLower(performanceName); int numRows = dataTableGetNumRows(DATATABLE_PERFORMANCE); for (int row = 0; row < numRows; ++row) { int rowTypeHash = dataTableGetInt(DATATABLE_PERFORMANCE, row, "type"); if (rowTypeHash == typeHash) { int rowInstrumentNumber = dataTableGetInt(DATATABLE_PERFORMANCE, row, "instrumentAudioId"); if (rowInstrumentNumber == instrumentNumber) { string rowPerformanceName = dataTableGetString(DATATABLE_PERFORMANCE, row, "performanceName"); if (rowPerformanceName == lowerPerformanceName) { return row+1; } } } } return 0; } boolean checkPerformanceType(int typeHash, int performanceIndex) { int rowTypeHash = dataTableGetInt(DATATABLE_PERFORMANCE, performanceIndex-1, "type"); return (rowTypeHash == typeHash); } // ---------------------------------------------------------------------- int findMatchingPerformanceIndex(int leaderPerformanceType, int instrumentNumber) { if (leaderPerformanceType == 0) return 0; // look up the performance name for the leader's performance type string performanceName = dataTableGetString(DATATABLE_PERFORMANCE, leaderPerformanceType-1, "performanceName"); // look up a the performance of the same name which uses the specified instrument int numRows = dataTableGetNumRows(DATATABLE_PERFORMANCE); for (int row = 0; row < numRows; ++row) { int rowTypeHash = dataTableGetInt(DATATABLE_PERFORMANCE, row, "type"); if (rowTypeHash == ##"music") { int rowInstrumentNumber = dataTableGetInt(DATATABLE_PERFORMANCE, row, "instrumentAudioId"); if (rowInstrumentNumber == instrumentNumber) { string rowPerformanceName = dataTableGetString(DATATABLE_PERFORMANCE, row, "performanceName"); if (rowPerformanceName == performanceName) { return row+1; } } } } return 0; } int findMatchingDroidPerformanceIndex(int leaderType, obj_id droid) { if(!pet_lib.isDroidPet(droid)) return 0; if(!hasObjVar(droid, "module_data.playback.tracks")) return 0; int[] tracks = getIntArrayObjVar(droid, "module_data.playback.tracks"); for(int i = 0; i < tracks.length; i++) { int index = tracks[i]; index--; int instrument = dataTableGetInt(DATATABLE_PERFORMANCE, index, "instrumentAudioId"); int match = findMatchingPerformanceIndex(leaderType, instrument); if((match != 0) && (match == tracks[i])) { return match; } } return 0; } int getInstrumentFromPerformanceType(int type) { type--; int instrument = dataTableGetInt(DATATABLE_PERFORMANCE, type, "instrumentAudioId"); return instrument; } boolean isHologramPerformer(obj_id who) { if(isPlayer(who)) return false; if(utils.hasScriptVar(who, "hologram_performer")) return true; return false; } obj_id[] getDanceMembers(obj_id who) { if(!isIdValid(who) || !exists(who)) { return null; } obj_id group = getGroupObject(who); if(!isIdValid(group)) { return null; } obj_id[] members = getGroupMemberIds(group); if(members == null || members.length <= 0) { return null; } resizeable obj_id[] validatedMembers = new obj_id[0]; for(int i = 0, j = members.length; i < j; i++) { if(!isIdValid(members[i]) || !exists(members[i])) { continue; } if(!isPlayer(members[i]) || getDistance(who, members[i]) > 64 || isIncapacitated(members[i]) || isDead(members[i]) || !utils.isProfession(members[i], utils.ENTERTAINER)) { continue; } utils.addElement(validatedMembers, members[i]); } return validatedMembers; } // ---------------------------------------------------------------------- obj_id[] getBandMembers(obj_id who) { // If grouped, everyone in the group with the musician command is considered in the band. obj_id group = getGroupObject(who); if (isIdValid(group)) { obj_id[] members = getGroupMemberIds(group); if (members != null) { int count = 0; for (int i = 0; i < members.length; ++i) { if (isPlayer(members[i]) || isHologramPerformer(members[i]) || (pet_lib.isDroidPet(members[i]) && hasObjVar(members[i], "module_data.playback"))) { ++count; } } if (count > 0) { obj_id[] ret = new obj_id[count]; count = 0; for (int i = 0; i < members.length; ++i) { if (isPlayer(members[i]) || isHologramPerformer(members[i]) || (pet_lib.isDroidPet(members[i]) && hasObjVar(members[i], "module_data.playback"))) { ret[count] = members[i]; ++count; } } return ret; } } // If noone in the group has the musician command, there isn't a band. return null; } // If ungrouped, the person is considered their own band if they have the musician command. if (isPlayer(who) || isHologramPerformer(who) || (pet_lib.isDroidPet(who) && hasObjVar(who, "module_data.playback"))) { obj_id[] ret = new obj_id[1]; ret[0] = who; return ret; } // There isn't a band at all. return null; } // ---------------------------------------------------------------------- void startPlaying(obj_id actor, int performanceIndex, int performanceStartTime, int instrumentNumber) { dictionary params; setPerformanceType(actor, performanceIndex); setPerformanceStartTime(actor, performanceStartTime); //get my listen target, if it is null, set it to me. if(!isIdValid(getPerformanceListenTarget(actor))) setPerformanceListenTarget(actor, actor); attachScript(actor, MUSIC_HEARTBEAT_SCRIPT); if(!pet_lib.isDroidPet(actor) && !isHologramPerformer(actor)) { sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_START, PERFORMANCE_TYPE_MUSIC); params = new dictionary(); params.put("performer", actor); broadcastMessage("handlePerformerStartPerforming", params); } params = new dictionary(); params.put("performanceIndex", performanceIndex); params.put("instrumentNumber", instrumentNumber); params.put("sequence", 0); messageTo(actor, "OnPulse", params, PERFORMANCE_HEARTBEAT_TIME, false); } // ---------------------------------------------------------------------- void stopPlaying(obj_id actor) { makeOthersStopListening(actor); int type = getPerformanceType(actor); if(type != 0) utils.setScriptVar(actor, "performance.performance_delay", getGameTime()); dictionary params; // Not using this message anymore ai now subscribe to "handlePerformerStopPerforming" //sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_STOP, PERFORMANCE_TYPE_MUSIC); if(!pet_lib.isDroidPet(actor) && !isHologramPerformer(actor)) { params = new dictionary(); params.put("performer", actor); params.put("check", "dancer"); broadcastMessage("handlePerformerStopPerforming", params); dictionary d = new dictionary(); d.put("commandType", HOLOGRAM_COMMAND_STOP_SONG); broadcastMessage("handleHologramPerformanceCommand", d); } messageTo(actor, "OnPerformanceEnd", null, 0.0f, false); detachScript(actor, performance.POST_PERFORMANCE); setPerformanceType(actor, 0); setPerformanceStartTime(actor, 0); if (utils.hasScriptVar(actor, VAR_PERFORM_INSPIRATION)) stopInspiration(actor); } // ---------------------------------------------------------------------- void startMusic(obj_id actor, string songName, int instrumentNumber) { session.logActivity(actor, session.ACTIVITY_ENTERTAINED); if(!pet_lib.isDroidPet(actor)) { if (getPerformanceType(actor) != 0) { if (!hasScript(actor, MUSIC_HEARTBEAT_SCRIPT) && !hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { stopPlaying(actor); if (hasObjVar(actor, performance.VAR_PERFORM)) { removeObjVar(actor, performance.VAR_PERFORM); } } else { performanceMessageToSelf(actor, null, SID_ALREADY_PERFORMING_SELF); return; } } instrumentNumber = getInstrumentAudioId(actor); if (instrumentNumber == 0) { if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); performanceMessageToSelf(master, null, SID_MUSIC_HOLOGRAM_NO_INSTRUMENT); } else performanceMessageToSelf(actor, null, SID_MUSIC_NO_INSTRUMENT); return; } } //Check to see if the player is in music outro roundtime. if (getIntObjVar(actor, VAR_PERFORM_OUTRO) == 1) { performanceMessageToSelf(actor, null, SID_MUSIC_OUTRO_WAIT); return; } boolean activeBandSong = false; int performanceIndex = 0; int performanceStartTime = 0; obj_id[] bandMembers = getBandMembers(actor); // Check to see if the band is playing a song for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (player == actor) continue; if (!hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) continue; int memberPerformanceIndex = getPerformanceType(player); if (memberPerformanceIndex != 0) { if(!pet_lib.isDroidPet(actor)) { performanceIndex = findMatchingPerformanceIndex(memberPerformanceIndex, instrumentNumber); } else { performanceIndex = findMatchingDroidPerformanceIndex(memberPerformanceIndex, actor); } performanceStartTime = getPerformanceStartTime(player); activeBandSong = true; break; } } if (!activeBandSong) { if (songName.length() < 1) { if (!displayAvailableMusic(actor, false, false)) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } performanceIndex = lookupPerformanceIndex(##"music", songName, instrumentNumber); performanceStartTime = getGameTime(); } if (performanceIndex == 0) { if(!pet_lib.isDroidPet(actor)) performanceMessageToSelf(actor, null, SID_MUSIC_INVALID_SONG); else performanceMessageToMaster(actor, null, SID_MUSIC_TRACK_NOT_AVAILABLE); return; } if (!notShapechanged(actor)) { return; } if (!pet_lib.isDroidPet(actor) && !canUseInstrument(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_INSTRUMENT); return; } if (!pet_lib.isDroidPet(actor) && !canPerformSong(actor, performanceIndex)) { if (activeBandSong) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_BAND); else performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } // start the performance startPlaying(actor, performanceIndex, performanceStartTime, instrumentNumber); dictionary d = new dictionary(); d.put("commandType", HOLOGRAM_COMMAND_START_SONG); d.put("songName", songName); broadcastMessage("handleHologramPerformanceCommand", d); if ( hasScript(actor, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("playingMusic", 1); messageTo(actor, "handleNewPlayerEntertainerAction", webster, 1, false); } if(!!pet_lib.isDroidPet(actor) && !isHologramPerformer(actor)) { if (activeBandSong) performanceMessageToSelf(actor, null, SID_MUSIC_JOIN_BAND_SELF); else performanceMessageToSelf(actor, null, SID_MUSIC_START_SELF); performanceMessageToBand(actor, null, SID_MUSIC_START_OTHER); performanceMessageToBandListeners(actor, null, SID_MUSIC_START_OTHER); } } void startMusic(obj_id actor, string songName) { startMusic(actor, songName, 0); } // ---------------------------------------------------------------------- void startBand(obj_id actor, string songName, int instrumentNumber) { if(!pet_lib.isDroidPet(actor)) { instrumentNumber = getInstrumentAudioId(actor); if (instrumentNumber == 0) { if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); performanceMessageToSelf(master, null, SID_MUSIC_HOLOGRAM_NO_INSTRUMENT); } else performanceMessageToSelf(actor, null, SID_MUSIC_NO_INSTRUMENT); return; } } //Check to see if the player is in music outro roundtime. if (getIntObjVar(actor, VAR_PERFORM_OUTRO) == 1) { performanceMessageToSelf(actor, null, SID_MUSIC_OUTRO_WAIT); return; } boolean activeSong = false; int performanceIndex = 0; int performanceStartTime = 0; obj_id[] bandMembers = getBandMembers(actor); // Check to see if the band is already playing a song. for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (!hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) continue; int memberPerformanceIndex = getPerformanceType(player); if (memberPerformanceIndex != 0) { performanceIndex = findMatchingPerformanceIndex(memberPerformanceIndex, instrumentNumber); performanceStartTime = getPerformanceStartTime(player); activeSong = true; break; } } if (!activeSong) { if (songName.length() < 1) { if (!displayAvailableMusic(actor, true, false)) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } performanceIndex = lookupPerformanceIndex(##"music", songName, instrumentNumber); performanceStartTime = getGameTime(); } if (!notShapechanged(actor)) { return; } if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_INVALID_SONG); return; } if (!canUseInstrument(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_INSTRUMENT); return; } if (!canPerformSong(actor, performanceIndex)) { if (activeSong) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_BAND); else performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } // start the performance startPlaying(actor, performanceIndex, performanceStartTime, instrumentNumber); if ( hasScript(actor, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("playingMusic", 1); messageTo(actor, "handleNewPlayerEntertainerAction", webster, 1, false); } // start up any other group members if appropriate boolean bandMemberLackSkill = false; for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (player == actor) continue; if (!isPlayer(player) && !pet_lib.isDroidPet(player) && !isHologramPerformer(player)) continue; if (getPerformanceType(player) != 0) { if (!hasScript(actor, MUSIC_HEARTBEAT_SCRIPT) && !hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { stopPlaying(actor); if (hasObjVar(actor, performance.VAR_PERFORM)) { removeObjVar(actor, performance.VAR_PERFORM); } } else continue; } if (getDistance(actor, player) > PERFORMANCE_BAND_MEMBER_RANGE) continue; int memberInstrumentNumber = 0; if(!pet_lib.isDroidPet(player)) { memberInstrumentNumber = getInstrumentAudioId(player); if (memberInstrumentNumber == 0) continue; } int memberPerformanceIndex = 0; if(!pet_lib.isDroidPet(player)) { memberPerformanceIndex = findMatchingPerformanceIndex(performanceIndex, memberInstrumentNumber); } else { memberPerformanceIndex = findMatchingDroidPerformanceIndex(performanceIndex, player); } if (memberPerformanceIndex != 0) { if (!notShapechanged(actor)) { continue; } if (!pet_lib.isDroidPet(player) && !canUseInstrument(player, memberPerformanceIndex)) { performanceMessageToSelf(player, null, SID_MUSIC_LACK_SKILL_INSTRUMENT); continue; } if(!pet_lib.isDroidPet(player)){ if (canPerformSong(player, memberPerformanceIndex)) { startPlaying(player, memberPerformanceIndex, performanceStartTime, memberInstrumentNumber); } else { performanceMessageToSelf(player, null, SID_MUSIC_LACK_SKILL_SONG_BAND); bandMemberLackSkill = true; } } else { memberInstrumentNumber = getInstrumentFromPerformanceType(memberPerformanceIndex); startPlaying(player, memberPerformanceIndex, performanceStartTime, memberInstrumentNumber); } } else { if(pet_lib.isDroidPet(player)) performanceMessageToMaster(player, null, SID_MUSIC_TRACK_NOT_AVAILABLE); } } if (activeSong) { performanceMessageToSelf(actor, null, SID_MUSIC_BAND_JOIN_SONG_SELF); performanceMessageToSelf(actor, null, SID_MUSIC_BAND_JOIN_SONG_MEMBERS); } else { performanceMessageToSelf(actor, null, SID_MUSIC_START_BAND_SELF); performanceMessageToBand(actor, null, SID_MUSIC_START_BAND_MEMBERS); } performanceMessageToBandListeners(actor, null, SID_MUSIC_START_BAND_OTHER); if (bandMemberLackSkill) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_BAND_MEMBER); } void startBand(obj_id actor, string songName) { startBand(actor, songName, 0); } // ---------------------------------------------------------------------- void startTroupe(obj_id actor, string danceName) { boolean activeDance = false; int performanceIndex = 0; int performanceStartTime = 0; obj_id[] bandMembers = getBandMembers(actor); // Check to see if the band is already Dancing. for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (hasScript(player, DANCE_HEARTBEAT_SCRIPT)) { stopDance(player); } } for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; danceName = utils.getStringScriptVar(player, VAR_CURRENT_DANCE); utils.removeScriptVar(player, VAR_CURRENT_DANCE); startDance(player, danceName); } } // ---------------------------------------------------------------------- void stopMusic(obj_id actor) { if(hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_MUSIC_NOT_PERFORMING); } else if (hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_MUSIC_PREPARE_STOP_SELF); specialFlourish(actor, SPECIAL_FLOURISH_OUTRO); // Apply a roundtime so the player cannot start again during the stopMusic outro. setObjVar(actor, VAR_PERFORM_OUTRO, 1); attachScript(actor, POST_PERFORMANCE); messageTo(actor, "OnClearOutro", null, PERFORMANCE_OUTRO_ROUNDTIME, false); } else { stopPlaying(actor); if (hasObjVar(actor, performance.VAR_PERFORM)) removeObjVar(actor, performance.VAR_PERFORM); if (hasObjVar(actor, performance.VAR_PERFORM_OUTRO)) removeObjVar(actor, performance.VAR_PERFORM_OUTRO); performanceMessageToSelf(actor, null, SID_MUSIC_NOT_PERFORMING); } } void stopMusicNow(obj_id actor) { if (hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_MUSIC_STOP_SELF); if(!isHologramPerformer(actor)) { performanceMessageToBand(actor, null, SID_MUSIC_STOP_OTHER); performanceMessageToBandListeners(actor, null, SID_MUSIC_STOP_OTHER); } } stopPlaying(actor); } // ---------------------------------------------------------------------- void stopBand(obj_id actor) { obj_id[] bandMembers = getBandMembers(actor); if (bandMembers != null) { performanceMessageToSelf(actor, null, SID_MUSIC_PREPARE_STOP_BAND_SELF); performanceMessageToBand(actor, null, SID_MUSIC_PREPARE_STOP_BAND_MEMBERS); boolean bandStop = false; for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) { specialFlourish(player, SPECIAL_FLOURISH_OUTRO); dictionary params = new dictionary(); if (player == actor) { params.put("leader", 1 ); } else { params.put("leader", 0 ); } // Apply a roundtime so the player cannot start again during the stopMusic outro. setObjVar(player, VAR_PERFORM_OUTRO, 1); attachScript(player, POST_PERFORMANCE); messageTo(player, "OnClearBandOutro", params, PERFORMANCE_OUTRO_ROUNDTIME, false); } } } } // ---------------------------------------------------------------------- void changeMusic(obj_id actor, string songName, int instrumentNumber) { if (!hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_MUSIC_MUST_BE_PERFORMING_SELF); return; } instrumentNumber = getInstrumentAudioId(actor); if (instrumentNumber == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_NO_INSTRUMENT); return; } //Check to see if the player is in music outro roundtime. if (getIntObjVar(actor, VAR_PERFORM_OUTRO) == 1) { performanceMessageToSelf(actor, null, SID_MUSIC_OUTRO_WAIT); return; } boolean activeBandSong = false; obj_id[] bandMembers = getBandMembers(actor); // Check to see if the band is playing a song for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (player == actor) continue; if (!hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) continue; int memberPerformanceIndex = getPerformanceType(player); if (memberPerformanceIndex != 0) { activeBandSong = true; break; } } if (activeBandSong) { performanceMessageToSelf(actor, null, SID_MUSIC_MUST_MATCH_BAND); return; } if (songName.length() < 1) { if (!displayAvailableMusic(actor, false, true)) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"music", songName, instrumentNumber); int performanceStartTime = getGameTime(); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_INVALID_SONG); return; } if (!notShapechanged(actor)) { return; } if (!canPerformSong(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } // change the performance setPerformanceType(actor, performanceIndex); queueCommand(actor, ##"showMusicianVisuals", null, "1", COMMAND_PRIORITY_IMMEDIATE); dictionary d = new dictionary(); d.put("songName", songName); d.put("commandType", HOLOGRAM_COMMAND_CHANGE_SONG); broadcastMessage("handleHologramPerformanceCommand", d); } void changeMusic(obj_id actor, string songName) { changeMusic(actor, songName, 0); } // ---------------------------------------------------------------------- void changeBandMusic(obj_id actor, string songName, int instrumentNumber) { if (!hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_MUSIC_MUST_BE_PERFORMING_SELF); return; } instrumentNumber = getInstrumentAudioId(actor); if (instrumentNumber == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_NO_INSTRUMENT); return; } //Check to see if the player is in music outro roundtime. if (getIntObjVar(actor, VAR_PERFORM_OUTRO) == 1) { performanceMessageToSelf(actor, null, SID_MUSIC_OUTRO_WAIT); return; } if (songName.length() < 1) { if (!displayAvailableMusic(actor, true, true)) performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"music", songName, instrumentNumber); int performanceStartTime = getGameTime(); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_INVALID_SONG); return; } if (!notShapechanged(actor)) { return; } if (!canPerformSong(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_MUSIC_LACK_SKILL_SONG_SELF); return; } // change the performance setPerformanceType(actor, performanceIndex); queueCommand(actor, ##"showMusicianVisuals", null, "1", COMMAND_PRIORITY_IMMEDIATE); obj_id[] bandMembers = getBandMembers(actor); for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (player == actor) continue; if (!hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) continue; if(!pet_lib.isDroidPet(player)) { int memberInstrumentNumber = getInstrumentAudioId(player); if (memberInstrumentNumber == 0) continue; int memberPerformanceIndex = findMatchingPerformanceIndex(performanceIndex, memberInstrumentNumber); if (!notShapechanged(actor)) { stopMusicNow(player); } if (memberPerformanceIndex != 0 && canPerformSong(player, memberPerformanceIndex)) { if (!hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) startPlaying(player, memberPerformanceIndex, 1, memberInstrumentNumber); setPerformanceType(player, memberPerformanceIndex); queueCommand(player, ##"showMusicianVisuals", null, "1", COMMAND_PRIORITY_IMMEDIATE); } else { performanceMessageToSelf(player, null, SID_MUSIC_LACK_SKILL_SONG_BAND); stopMusicNow(player); } if(!canUseInstrument(player, memberInstrumentNumber)) { performanceMessageToSelf(player, null, SID_MUSIC_LACK_SKILL_INSTRUMENT); stopMusicNow(player); } } else { int memberPerformanceIndex = findMatchingDroidPerformanceIndex(performanceIndex, player); if(memberPerformanceIndex != 0) { setPerformanceType(player, memberPerformanceIndex); } else { performanceMessageToMaster(player, null, SID_MUSIC_TRACK_NOT_AVAILABLE); stopMusicNow(player); } } } } void changeBandMusic(obj_id actor, string songName) { changeBandMusic(actor, songName, 0); } void startDance(obj_id actor, string danceName) { startDance(actor, danceName, true); } // ---------------------------------------------------------------------- void startDance(obj_id actor, string danceName, boolean displayDances) { session.logActivity(actor, session.ACTIVITY_ENTERTAINED); if(danceName.length() < 1) { if(displayDances) { displayAvailableDances(actor, false); } return; } if (getPerformanceType(actor) != 0) { performanceMessageToSelf(actor, null, SID_ALREADY_PERFORMING_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"dance", danceName, 0); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_DANCE_UNKNOWN_SELF); return; } if (!notShapechanged(actor)) { return; } // Check to see if the player has the skill to perform the selected dance. if (!canPerformDance(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_DANCE_LACK_SKILL_SELF); return; } setClientUsesAnimationLocomotion(actor, true); // start the performance performanceMessageToSelf(actor, null, SID_DANCE_START_SELF); performanceMessageToWatchers(actor, null, SID_DANCE_START_OTHER); //if dancer has no watcher, set themselve as thier watch target if(!isIdValid(getPerformanceWatchTarget(actor))) setPerformanceWatchTarget(actor, actor); dictionary params; int startTime = getGameTime(); setPerformanceType(actor, performanceIndex); setPerformanceStartTime(actor, startTime); attachScript(actor, DANCE_HEARTBEAT_SCRIPT); if(!isHologramPerformer(actor)) { sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_START, PERFORMANCE_TYPE_DANCE); params = new dictionary(); params.put("performer", actor); broadcastMessage("handlePerformerStartPerforming", params); dictionary d = new dictionary(); d.put("danceName", danceName); d.put("commandType", HOLOGRAM_COMMAND_START_DANCE); utils.setScriptVar(actor, VAR_CURRENT_DANCE, danceName); broadcastMessage("handleHologramPerformanceCommand", d); if ( hasScript(actor, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("startedDancing", 1); messageTo(actor, "handleNewPlayerEntertainerAction", webster, 1, false); } } params = new dictionary(); params.put("performanceIndex", performanceIndex); params.put("sequence", 0); messageTo(actor, "OnPulse", params, PERFORMANCE_HEARTBEAT_TIME, false); } // ---------------------------------------------------------------------- void stopDance(obj_id actor) { int type = getPerformanceType(actor); if(type != 0) utils.setScriptVar(actor, "performance.performance_delay", getGameTime()); setClientUsesAnimationLocomotion(actor, false); queueCommand(actor, ##"showDanceVisuals", null, "0", COMMAND_PRIORITY_IMMEDIATE); if(utils.hasScriptVar(actor, "event.dance_party") ) { utils.removeScriptVar(actor, "event.dance_party"); } if (hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { // Not using this message anymore ai now subscribe to "handlePerformerStopPerforming" //sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_STOP, PERFORMANCE_TYPE_DANCE); if(!isHologramPerformer(actor)) { dictionary params = new dictionary(); params.put("performer", actor); params.put("check", "musician"); broadcastMessage("handlePerformerStopPerforming", params); // message to the entertainer if(!utils.hasScriptVar(actor, "stopDanceMessage")) { utils.setScriptVar(actor, "stopDanceMessage", 1); performanceMessageToSelf(actor, null, SID_DANCE_STOP_SELF); messageTo(actor, "handleStopDanceMessage", null, 1.0f, false); // stop staring at me! makeOthersStopWatching(actor); } // message to the watchers performanceMessageToWatchers(actor, null, SID_DANCE_STOP_OTHER); dictionary d = new dictionary(); d.put("commandType", HOLOGRAM_COMMAND_STOP_DANCE); broadcastMessage("handleHologramPerformanceCommand", d); } messageTo(actor, "OnPerformanceEnd", null, 0.0f, false); setPerformanceType(actor, 0); setPerformanceStartTime(actor, 0); } else { if (hasObjVar(actor, performance.VAR_PERFORM)) { removeObjVar(actor, performance.VAR_PERFORM); } performanceMessageToSelf(actor, null, SID_DANCE_NOT_PERFORMING); } if (utils.hasScriptVar(actor, VAR_PERFORM_INSPIRATION)) stopInspiration(actor); } // ---------------------------------------------------------------------- void makeOthersStopWatching(obj_id actor) { obj_id[] watcherToStop = getPerformanceWatchersInRange(actor, PERFORMANCE_HEAL_RANGE); for(int i = 0; i < watcherToStop.length; i++) { if(watcherToStop[i] != actor) { queueCommand(watcherToStop[i], ##"stopwatching", null, "", COMMAND_PRIORITY_DEFAULT); } } } // ----------------------------------------------------------------------- void makeOthersStopListening(obj_id actor) { obj_id[] watcherToStop = getPerformanceListenersInRange(actor, PERFORMANCE_HEAL_RANGE); for(int i = 0; i < watcherToStop.length; i++) { if(watcherToStop[i] != actor) { queueCommand(watcherToStop[i], ##"stoplistening", null, "", COMMAND_PRIORITY_DEFAULT); } } } // ----------------------------------------------------------------------- void changeDance(obj_id actor, string danceName) { changeDance(actor, danceName, true); } void changeDance(obj_id actor, string danceName, boolean displayDances) { if(danceName.length() < 1) { if(displayDances) { displayAvailableDances(actor, true); } return; } if (!hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_DANCE_MUST_BE_PERFORMING_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"dance", danceName, 0); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_DANCE_UNKNOWN_SELF); return; } if (!notShapechanged(actor)) { return; } // Check to see if the player has the skill to perform the selected dance. if (!canPerformDance(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_DANCE_LACK_SKILL_SELF); return; } setPerformanceType(actor, performanceIndex); queueCommand(actor, ##"showDanceVisuals", null, "1", COMMAND_PRIORITY_IMMEDIATE); dictionary d = new dictionary(); d.put("danceName", danceName); d.put("commandType", HOLOGRAM_COMMAND_CHANGE_DANCE); broadcastMessage("handleHologramPerformanceCommand", d); } // ---------------------------------------------------------------------- void joinBand(obj_id actor) { if (getPerformanceType(actor) == 0) { return; } boolean activeBandSong = false; int performanceIndex = 0; int performanceStartTime = 0; int instrumentNumber = getInstrumentAudioId(actor); obj_id[] bandMembers = getBandMembers(actor); // Check to see if the band is playing a song for (int i = 0; i < bandMembers.length; ++i) { obj_id player = bandMembers[i]; if (player == actor) continue; if (!hasScript(player, MUSIC_HEARTBEAT_SCRIPT)) continue; int memberPerformanceIndex = getPerformanceType(player); if (memberPerformanceIndex != 0) { performanceIndex = findMatchingPerformanceIndex(memberPerformanceIndex, instrumentNumber); performanceStartTime = getPerformanceStartTime(player); activeBandSong = true; break; } } if (activeBandSong) { if (getPerformanceType(actor) == performanceIndex) { setPerformanceStartTime(actor, performanceStartTime); } else { stopPlaying(actor); performanceMessageToSelf(actor, null, SID_MUSIC_JOIN_BAND_STOP); } } return; } // ---------------------------------------------------------------------- void sendNpcsEntertainmentMessage(obj_id actor, string message, string perf_type) { int count = 0; obj_id[] npcs = getAllNpcs( getLocation(actor), 10.0f ); if ( npcs != null) { dictionary params = new dictionary(); params.put("entertainer", actor ); params.put("perf_type", perf_type); for (int i = 0; i < npcs.length; i++ ) { if ( hasScript( npcs[i], "ai.ai" )) // Only send message to ai with the handler { if ( !utils.hasScriptVar( npcs[i], "ai.listeningTo" ) ) // Only send message to ai not listening to someone else { messageTo( npcs[i], message, params, 0, false ); count++; if (count > 4) // Only send the message to the first few ai in the list return; } } } } } // ---------------------------------------------------------------------- void flourish(obj_id actor, int index) { //Check to see if the player is performing if (getPerformanceType(actor) == 0) { performanceMessageToSelf(actor, null, SID_FLOURISH_NOT_PERFORMING); return; } if ((index < 1) || (index > 8)) { performanceMessageToSelf(actor, null, SID_FLOURISH_NOT_VALID); return; } // Check total flourishes done this tick, no more than 4 allowed (to prevent flourish spamming for medic exploit) if (hasObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL)) { int flourish_total = getIntObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL); if (flourish_total > 4) return; } //Check to see if the player is already performing a flourish. if (getIntObjVar(actor, VAR_PERFORM_FLOURISH) == 1) { performanceMessageToSelf(actor, null, SID_FLOURISH_WAIT_SELF); return; } else { setObjVar(actor, VAR_PERFORM_FLOURISH, 1); dictionary params = new dictionary(); messageTo(actor, "OnClearFlourish", params, PERFORMANCE_FLOURISH_ROUNDTIME, false); } float flourishCost = 0; string entertainmentType = ""; if (hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { flourishCost = 0.5f; entertainmentType = "music"; } else if (hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { flourishCost = 1f; entertainmentType = "dance"; } else if (hasScript(actor, JUGGLE_HEARTBEAT_SCRIPT)) { flourishCost = 1f; entertainmentType = "juggle"; } if (applyPerformanceActionCost(actor, flourishCost)) { performanceMessageToSelf(actor, null, SID_FLOURISH_PERFORM); } else { performanceMessageToSelf(actor, null, SID_FLOURISH_TOO_TIRED); return; } // Increment the flourish counter int flourish_count = getIntObjVar(actor, VAR_PERFORM_FLOURISH_COUNT); flourish_count++; // With the addition of the newer songs that are longer than 5 second loop times, this calculation is confusing to players // wherein some songs you can do two flourishes per pulse, and some you can do only one. Setting it to a flat flourish max of // two (as setting it to one would be a nerf). // int flourish_max = (int) (10 / getPerformanceLoopDuration(getPerformanceType(actor))); // if(flourish_max < 1) // flourish_max = 1; int flourish_max = 2; LOG("entertainer_xp", "Performance Loop Duration = " + getPerformanceLoopDuration(getPerformanceType(actor))); LOG("entertainer_xp", "Max Fourishes = " + flourish_max); if (flourish_count > flourish_max) flourish_count = flourish_max; setObjVar(actor, VAR_PERFORM_FLOURISH_COUNT, flourish_count); // Increment the flourish total (to prevent flourish spamming for medic exploit) flourish_count = getIntObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL); flourish_count++; setObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL, flourish_count); if ( hasScript(actor, "theme_park.new_player.new_player") ) { dictionary webster = new dictionary(); webster.put("addingFlourish", 1); webster.put("entertainmentType", entertainmentType); messageTo(actor, "handleNewPlayerEntertainerAction", webster, 1, false); } dictionary params = new dictionary(); params.put("performanceIndex", getPerformanceType(actor)); params.put("flourishIndex", index); params.put("mistakeChance", getPerformanceMistakeChance(actor)); messageTo(actor, "OnFlourish", params, 0.0f, false); } // This function is used to pass special case flourishes to music system for special situations like outros and pausing of music. void specialFlourish(obj_id actor, int index) { //Check to see if the player is performing if (getPerformanceType(actor) == 0) { return; } dictionary params = new dictionary(); params.put("performanceIndex", getPerformanceType(actor)); params.put("flourishIndex", index); messageTo(actor, "OnSpecialFlourish", params, 0.0f, false); } void bandFlourish(obj_id actor, int index, string instrument) { //Check to see if the player is performing if (getPerformanceType(actor) == 0) { performanceMessageToSelf(actor, null, SID_FLOURISH_NOT_PERFORMING); return; } if ((index < 0) || (index > 8)) { performanceMessageToSelf(actor, null, SID_FLOURISH_NOT_VALID); return; } int instrumentNum = -1; if (instrument != null) { if(!pet_lib.isDroidPet(actor)) instrumentNum = lookupInstrumentNumber(actor, instrument); else instrumentNum = getInstrumentFromPerformanceType(getPerformanceType(actor)); } LOG ("performance_music", "Band Flourish: " + index + ", Instrument: " + instrument + "(" + instrumentNum + ")"); // Determine who should play the flourish int band_size = 0; obj_id[] band_members = new obj_id[20]; if (instrumentNum > 0) { // Find the band members that are using the specified instrument. obj_id group = getGroupObject(actor); if (isIdValid(group)) { obj_id[] members = getGroupMemberIds(group); for (int i = 0; i < members.length; ++i) { if(!pet_lib.isDroidPet(members[i])) { LOG ("performance_music", "My instrument is " + getInstrumentAudioId(members[i])); if(hasScript(members[i], MUSIC_HEARTBEAT_SCRIPT) && (getInstrumentAudioId(members[i]) == instrumentNum)) { band_members[band_size] = members[i]; ++band_size; } } else { int instrumentID = getInstrumentFromPerformanceType(getPerformanceType(members[i])); if(hasScript(members[i], MUSIC_HEARTBEAT_SCRIPT) && (instrumentID == instrumentNum)) { band_members[band_size] = members[i]; ++band_size; } } } } } else if (instrumentNum == -1) { string heartbeat_script; if (hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) { heartbeat_script = DANCE_HEARTBEAT_SCRIPT; } else if (hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) { heartbeat_script = MUSIC_HEARTBEAT_SCRIPT; } else if (hasScript(actor, JUGGLE_HEARTBEAT_SCRIPT)) { heartbeat_script = JUGGLE_HEARTBEAT_SCRIPT; } else { performanceMessageToSelf(actor, null, SID_FLOURISH_NOT_PERFORMING); return; } obj_id group = getGroupObject(actor); if (isIdValid(group)) { obj_id[] members = getGroupMemberIds(group); for (int i = 0; i < members.length; ++i) { if (hasScript(members[i], heartbeat_script)) { band_members[band_size] = members[i]; ++band_size; } } } } for (int i = 0; i < band_size; i++) { obj_id player = band_members[i]; if (hasObjVar(player, VAR_PERFORM_NO_BAND_FLOURISH)) continue; if (getDistance(actor, player) > PERFORMANCE_BAND_MEMBER_RANGE) continue; //Check to see if the player is already performing a flourish. if (getIntObjVar(player, VAR_PERFORM_FLOURISH) == 1) { performanceMessageToSelf(player, null, SID_FLOURISH_WAIT_SELF); continue; } else { setObjVar(player, VAR_PERFORM_FLOURISH, 1); dictionary params = new dictionary(); messageTo(player, "OnClearFlourish", params, PERFORMANCE_FLOURISH_ROUNDTIME, false); } if (applyPerformanceActionCost(player, 0.5f)) { performanceMessageToSelf(player, null, SID_FLOURISH_PERFORM); } else { performanceMessageToSelf(player, null, SID_FLOURISH_TOO_TIRED); continue; } // Increment the flourish counter if (player == actor) { int flourish_count = getIntObjVar(player, VAR_PERFORM_FLOURISH_COUNT); flourish_count++; int flourish_max = (int) (10 / getPerformanceLoopDuration(getPerformanceType(player))); if (flourish_count > flourish_max) flourish_count = flourish_max; setObjVar(player, VAR_PERFORM_FLOURISH_COUNT, flourish_count); } else { performanceMessageToPerson(player, actor, actor, SID_FLOURISH_PERFORM_BAND_MEMBER); } // Increment the flourish total (to prevent flourish spamming for medic exploit) int flourish_count = getIntObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL); flourish_count++; setObjVar(actor, VAR_PERFORM_FLOURISH_TOTAL, flourish_count); dictionary params = new dictionary(); if(index == SPECIAL_FLOURISH_PAUSE_MUSIC) { specialFlourish(player, index); } else { params.put("performanceIndex", getPerformanceType(player)); params.put("flourishIndex", index); params.put("mistakeChance", getPerformanceMistakeChance(player)); messageTo(player, "OnFlourish", params, 0.0f, false); performanceMessageToSelf(actor, null, SID_FLOURISH_PERFORM_BAND_SELF); } } } int lookupInstrumentNumber(obj_id actor, string instrument) { int instrumentCount = dataTableGetNumRows(DATATABLE_INSTRUMENT); string instrumentName[] = dataTableGetStringColumn(DATATABLE_INSTRUMENT, DATATABLE_COL_VISIBLE_NAME); for (int i = 0; i < instrumentCount; i++) { if (instrumentName[i].startsWith(instrument)) { return dataTableGetInt(DATATABLE_INSTRUMENT, i, DATATABLE_COL_INSTRUMENT_ID); } } performanceMessageToSelf(actor, null, SID_FLOURISH_INSTRUMENT_UNKNOWN); return 0; } // ---------------------------------------------------------------------- void effect(obj_id actor, int effectId, int effectLevel) { if(effectLevel < 1) effectLevel = 3; boolean mustPerform = getEffectPerformReq(effectId, effectLevel); int performanceIndex = getPerformanceType(actor); //Check to see if the player is performing if (mustPerform && (performanceIndex == 0)) { performanceMessageToSelf(actor, null, SID_EFFECT_NOT_PERFORMING); return; } //Check to see if the player is already performing an effect. if (getIntObjVar(actor, VAR_PERFORM_EFFECT) == 1) { performanceMessageToSelf(actor, null, SID_EFFECT_WAIT_SELF); return; } // find the completion time of the effect and set the completion message to send float effectRoundTime = getEffectDuration(effectId, effectLevel); setObjVar(actor, VAR_PERFORM_EFFECT, 1); dictionary params = new dictionary(); messageTo(actor, "OnClearEffect", params, effectRoundTime, false); // send the effect message params.put("performanceIndex", getPerformanceType(actor)); params.put("effectId", effectId); params.put("effectLevel", effectLevel); messageTo(actor, "OnEffect", params, 0.0f, false); } // ---------------------------------------------------------------------- void playEffectTarget(obj_id self, obj_id target, string effectName, string_id effectString) { performanceMessageToSelf(self, null, effectString); playClientEffectObj(self, effectName, target, ""); } // ---------------------------------------------------------------------- void playEffectLoc(obj_id self, location loc, string effectName, string_id effectString) { performanceMessageToSelf(self, null, effectString); playClientEffectLoc(self, effectName, loc, 0.0f); } // ---------------------------------------------------------------------- int getEffectIndex(int effectId, int effectLevel) { return ((effectId - 1) * 3) + (effectLevel - 1); } // ---------------------------------------------------------------------- boolean getEffectPerformReq(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return (dataTableGetInt(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_REQ_PERFORM) == 1); } // ---------------------------------------------------------------------- string getEffectPerformanceType(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return dataTableGetString(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_PERFORM_TYPE); } // ---------------------------------------------------------------------- int getEffectPerformSkillLevel(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return dataTableGetInt(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_REQ_SKILL_VAL); } // ---------------------------------------------------------------------- float getEffectDuration(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return dataTableGetFloat(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_DURATION); } // ---------------------------------------------------------------------- int getEffectActionCost(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return dataTableGetInt(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_ACTION_COST); } // ---------------------------------------------------------------------- int getEffectTargetType(int effectId, int effectLevel) { int effectIndex = getEffectIndex (effectId, effectLevel); return dataTableGetInt(DATATABLE_PERFORMANCE_EFFECT, effectIndex, DATATABLE_COL_EFFECT_TARGET_TYPE); } // ---------------------------------------------------------------------- int checkEffectLevel(obj_id actor, int effectId, int effectLevel) { boolean sendMessage = true; if (effectLevel == -1) { effectLevel = 3; sendMessage = false; } string requiredSkill = null; string performanceType = getEffectPerformanceType(effectId, effectLevel); if (hasScript(actor, MUSIC_HEARTBEAT_SCRIPT)) requiredSkill = "healing_music_ability"; else if (hasScript(actor, DANCE_HEARTBEAT_SCRIPT)) requiredSkill = "healing_dance_ability"; else if (hasScript(actor, JUGGLE_HEARTBEAT_SCRIPT)) requiredSkill = "healing_juggle_ability"; int requiredSkillVal = getEffectPerformSkillLevel(effectId, effectLevel); LOG ("entertainer_effect", "Performing Effect: " + effectId + ", Level: " + effectLevel); LOG ("entertainer_effect", "Required Skill: " + requiredSkill); int playerSkill = getSkillStatMod(actor, requiredSkill); LOG ("entertainer_effect", "Required Value: " + requiredSkillVal + ", Player Skill: " + playerSkill); while ((requiredSkillVal > playerSkill) && (effectLevel > 0)) { effectLevel -= 1; requiredSkillVal = getEffectPerformSkillLevel(effectId, effectLevel); if (sendMessage) { performanceMessageToSelf(actor, null, SID_EFFECT_LEVEL_TOO_HIGH); sendMessage = false; } } return effectLevel; } // ---------------------------------------------------------------------- void performanceMessageToPerson(obj_id person, obj_id actor, obj_id target, string_id message) { prose_package pp = new prose_package(); pp.stringId = message; if (isIdValid(actor)) pp.actor.set(getEncodedName(actor)); if (isIdValid(target)) pp.target.set(getEncodedName(target)); sendSystemMessageProse(person, pp); } // ---------------------------------------------------------------------- void performanceMessageToMaster(obj_id actor, obj_id target, string_id message) { if(!pet_lib.isDroidPet(actor)) return; obj_id master = getMaster(actor); if(isIdValid(master)) performanceMessageToPerson(master, actor, target, message); } // ---------------------------------------------------------------------- void performanceMessageToSelf(obj_id actor, obj_id target, string_id message) { performanceMessageToPerson(actor, actor, target, message); } // ---------------------------------------------------------------------- // // to array, but not to actor void performanceMessageToArray(obj_id[] people, obj_id actor, obj_id target, string_id message) { if (people != null) for (int i = 0; i < people.length; ++i) if (people[i] != actor) performanceMessageToPerson(people[i], actor, target, message); } // ---------------------------------------------------------------------- // to band members, but not to actor void performanceMessageToBand(obj_id actor, obj_id target, string_id message) { obj_id[] members = getBandMembers(actor); performanceMessageToArray(members, actor, target, message); } // ---------------------------------------------------------------------- // to everyone listening to band members, but not to band members void performanceMessageToBandListeners(obj_id actor, obj_id target, string_id message) { obj_id[] members = getBandMembers(actor); if (members != null) for (int i = 0; i < members.length; ++i) performanceMessageToListeners(members[i], target, message); } // ---------------------------------------------------------------------- // to everyone listening to actor, except actor void performanceMessageToListeners(obj_id actor, obj_id target, string_id message) { performanceMessageToArray(getPerformanceListenersInRange(actor, PERFORMANCE_HEAL_RANGE), actor, target, message); } // ---------------------------------------------------------------------- // to everyone watching actor, except actor void performanceMessageToWatchers(obj_id actor, obj_id target, string_id message) { performanceMessageToArray(getPerformanceWatchersInRange(actor, PERFORMANCE_HEAL_RANGE), actor, target, message); } // ====================================================================== int getPerformanceHealWoundMod(int perf_index) { if (perf_index == 0) return 0; return dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, "healMindWound"); } // ====================================================================== int getPerformanceHealShockMod(int perf_index) { if (perf_index == 0) return 0; return dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_HEAL_SHOCK); } int getPerformanceActionCost(int perf_index) { if (perf_index == 0) return 0; return dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_ACTION_COST); } float getPerformanceLoopDuration(int perf_index) { if (perf_index == 0) return 0; return dataTableGetFloat(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_LOOP_DURATION); } int getPerformanceBaseXp(int perf_index) { if (perf_index == 0) return 0; return dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_BASE_XP); } int getFlourishXpMod(int perf_index) { if (perf_index == 0) return 0; return dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_FLOURISH_XP_MOD); } boolean performanceHeal(obj_id actor, string perf_type, float modifier) { if(!isIdValid(actor)) return false; if(!isPlayer(actor)) return false; int can_heal = canPerformanceHeal(actor); if(can_heal == 0) return false; obj_id[] audience; if(perf_type.equals(PERFORMANCE_TYPE_DANCE)) audience = getPerformanceWatchersInRange(actor, PERFORMANCE_INSPIRE_RANGE); else if(perf_type.equals(PERFORMANCE_TYPE_MUSIC)) audience = getPerformanceListenersInRange(actor, PERFORMANCE_INSPIRE_RANGE); else return false; if(audience.length < 1) return false; int audienceMod = 0; // package for the target prose_package pt = new prose_package(); pt.target.set(actor); pt.stringId = new string_id("spam", "cured_clonesick"); // package for the actor prose_package pa = new prose_package(); pa.stringId = new string_id("spam", "cured_clonesick_actor"); // loop through audience see if anyone needs to be cured of cloning sickness for(int i = 0; i < audience.length; i++) { if(!isIdValid(audience[i]) || !exists(audience[i])) { continue; } if(checkDenyService(actor, audience[i])) continue; if(utils.hasScriptVar(audience[i], VAR_PERFORM_PAY_WAIT)) continue; if(buff.hasBuff(audience[i], "cloning_sickness")) { // remove buff buff.removeBuff(audience[i], "cloning_sickness"); playClientEffectObj(audience[i], "appearance/pt_heal.prt", audience[i], ""); if(!utils.hasScriptVar(audience[i], VAR_PERFROM_ALREADY_PAID)) { int charge = utils.getIntScriptVar(audience[i], performance.VAR_PERFORM_PAY_AGREE); if(charge > 0) { money.systemPayout(money.ACCT_PERFORM_ESCROW, actor, charge, "handlePayment", null); utils.setScriptVar(audience[i], VAR_PERFROM_ALREADY_PAID, 1); } } // notify target if(audience[i] != actor) sendSystemMessageProse(audience[i], pt); // notify actor pa.target.set(audience[i]); sendSystemMessageProse(actor, pa); audienceMod++; } if(buff.hasBuff(audience[i],"gcw_fatigue")) { if(groundquests.isQuestActive(actor, "gcw_entertain_fatigue") && factions.isSameFactionorFactionHelper(actor, audience[i])) { pt.stringId = new string_id("spam", "cured_fatigue"); pa.stringId = new string_id("spam", "cured_fatigued_actor"); //buff.decrementBuffStack(audience[i], "gcw_fatigue", 5); int stackSize = (int)buff.getBuffStackCount(audience[i], "gcw_fatigue"); if(stackSize <= 0) { continue; } else if(stackSize <= 5) { buff.removeBuff(audience[i], "gcw_fatigue"); } else if(stackSize > 5) { stackSize = stackSize -5; buff.removeBuff(audience[i], "gcw_fatigue"); buff.applyBuffWithStackCount(audience[i], "gcw_fatigue", stackSize); } groundquests.sendSignal(actor, "cureFatigue"); /*Check to see if we can add the entertainer to an existing participant list.*/ obj_id cityEggId = gcw.getInvasionSequencerNearby(actor); if(isValidId(cityEggId)) { trial.addNonInstanceFactionParticipant(actor, cityEggId); } // package for the target prose_package gcw_fatigue_pt = new prose_package(); pt.target.set(actor); pt.stringId = new string_id("spam", "cured_fatigue"); // package for the actor prose_package gcw_fatigue_pa = new prose_package(); pa.stringId = new string_id("spam", "cured_fatigued_actor"); playClientEffectObj(audience[i], "appearance/pt_heal.prt", audience[i], ""); if(!utils.hasScriptVar(audience[i], VAR_PERFROM_ALREADY_PAID)) { int charge = utils.getIntScriptVar(audience[i], performance.VAR_PERFORM_PAY_AGREE); if(charge > 0) { money.systemPayout(money.ACCT_PERFORM_ESCROW, actor, charge, "handlePayment", null); utils.setScriptVar(audience[i], VAR_PERFROM_ALREADY_PAID, 1); } } // notify target if(audience[i] != actor) sendSystemMessageProse(audience[i], pt); // notify actor pa.target.set(audience[i]); sendSystemMessageProse(actor, pa); audienceMod++; } } } // Grant some experience int experience = (CURE_CLONING_SICKNESS_XP * audienceMod); obj_id[] band = getBandMembers(actor); for (int i = 0; i < band.length; i++) xp.grantSocialStyleXp(band[i], xp.ENTERTAINER, experience); return true; } // ---------------------------------------------------------------------- float inspireGetMaxDuration(obj_id actor) { int can_heal = canPerformanceHeal(actor); float pctComplete = respec.getPercentageCompletion(actor, getSkillTemplate(actor)); float totInspireSkill = (pctComplete * 300.0f); //Update 8: Granting a bonus to Max Duration if using the Entertainment District City Spec. int city_id = city.checkCity(actor, false); if(city_id > 0 && (city.cityHasSpec(city_id, city.SF_SPEC_ENTERTAINER))) { totInspireSkill = totInspireSkill * 2.2f; //Doubling - ends up being about a 10% bonus due to dimishing returns formula. } // Diminishing returns formula // This should be a ~3 hour buff at max but in practice its only about 1 hour according to testing. Adding another flat 1800. float expertiseDurationIncreaseMod = getEnhancedSkillStatisticModifierUncapped(actor, "expertise_en_inspire_buff_duration_increase")*60; float maxDuration = (12100.0f - (12100.0f * (1.0f / ((totInspireSkill + (1.0f / 0.01f)) * 0.01f)))) + 3600.0f; maxDuration += expertiseDurationIncreaseMod; obj_id camp = camping.getCurrentAdvancedCamp(actor); if(isIdValid(camp)) { if(camping.isInEntertainmentCamp(actor, camp)) { float campEffectiveness = getFloatObjVar(camp, "modules.entertainer"); if (campEffectiveness < 1.0f) { maxDuration = maxDuration * campEffectiveness; } } } if (can_heal == 3) { maxDuration = maxDuration * 0.2f; } return maxDuration; } boolean inspire(obj_id actor, string perf_type) { if(!isIdValid(actor)) return false; if(!isPlayer(actor)) return false; int can_heal = canPerformanceHeal(actor); if(can_heal == 0) return false; obj_id[] audience; if(perf_type.equals(PERFORMANCE_TYPE_DANCE)) audience = getPerformanceWatchersInRange(actor, PERFORMANCE_INSPIRE_RANGE); else if(perf_type.equals(PERFORMANCE_TYPE_MUSIC)) audience = getPerformanceListenersInRange(actor, PERFORMANCE_INSPIRE_RANGE); else return false; if(audience.length < 1) return false; float maxDuration = inspireGetMaxDuration(actor); int audienceMod = 0; for(int i = 0; i < audience.length; i++) { if(audience[i] == actor) continue; if(checkDenyService(actor, audience[i])) continue; // if(!utils.hasScriptVar(audience[i], VAR_BUFF_TYPE)) // continue; if(utils.hasScriptVar(audience[i], VAR_PERFORM_PAY_WAIT)) continue; float inspirationScriptVarVal = 0.0f; if(utils.hasScriptVar(audience[i], VAR_PERFORM_INSPIRATION)) inspirationScriptVarVal = utils.getFloatScriptVar(audience[i], VAR_PERFORM_INSPIRATION); if(inspirationScriptVarVal == maxDuration) continue; int inspireBuffCrc = buff.getBuffOnTargetFromGroup(audience[i], "inspiration"); // if(inspireBuffCrc != 0) // buff.removeBuff(audience[i], inspireBuffCrc); float expertisePerTickBonusTime = getEnhancedSkillStatisticModifierUncapped(actor, "expertise_en_inspire_pulse_duration_increase")*60; float perTickMinutesAdded = expertisePerTickBonusTime + INSPIRATION_BUFF_SEGMENT; //Update 8: Granting an extra 3 minutes per tick if they have an Entertainment District Spec. int city_id = city.checkCity(actor, false); if(city_id > 0 && (city.cityHasSpec(city_id, city.SF_SPEC_ENTERTAINER))) { perTickMinutesAdded += 180; } inspirationScriptVarVal += perTickMinutesAdded; if(inspirationScriptVarVal > maxDuration) { inspirationScriptVarVal = maxDuration; if (!utils.hasScriptVar(audience[i], "performance.inspireMaxReached")) { showFlyTextPrivate(audience[i], audience[i], new string_id("performance", "buff_maxtime"), 0.66f, colors.LIGHTPINK.getR(), colors.LIGHTPINK.getG(), colors.LIGHTPINK.getB(), true); showFlyTextPrivate(audience[i], actor, new string_id("performance", "buff_maxtime"), 0.66f, colors.LIGHTPINK.getR(), colors.LIGHTPINK.getG(), colors.LIGHTPINK.getB(), true); utils.setScriptVar(audience[i], "performance.inspireMaxReached", 1); } } else { int perTickMinutesAddedInt = (int)perTickMinutesAdded/60; string_id strSpam = new string_id("spam", "buff_duration_tick_not_hardcoded"); prose_package pp = new prose_package(); pp = prose.setStringId(pp, strSpam); pp = prose.setDI(pp, perTickMinutesAddedInt); showFlyTextPrivate(audience[i], audience[i], pp, 0.66f, colors.LIGHTPINK.getR(), colors.LIGHTPINK.getG(), colors.LIGHTPINK.getB(), true); showFlyTextPrivate(audience[i], actor, pp, 0.66f, colors.LIGHTPINK.getR(), colors.LIGHTPINK.getG(), colors.LIGHTPINK.getB(), true); } // string buff_type = utils.getStringScriptVar(audience[i], VAR_BUFF_TYPE); // buff.applyBuff(audience[i], buff_type, inspirationScriptVarVal); utils.setScriptVar(audience[i], VAR_PERFORM_INSPIRATION, inspirationScriptVarVal); audienceMod++; } // Grant some experience int experience = (PERFORM_XP_INSPIRATION * audienceMod); obj_id[] band = getBandMembers(actor); for (int i = 0; i < band.length; i++) xp.grantSocialStyleXp(band[i], xp.ENTERTAINER, experience); return true; } // ---------------------------------------------------------------------- boolean performanceTargetedBuffFlourish(obj_id actor, string perf_type, float modifier) { // Removed Entertainer buffs for new HAM system /* if (!isIdValid(actor)) return false; if (!isPlayer(actor)) return false; if (modifier <= 0) return false; // Can only heal at cantinas or campsites. A value of 0 means that the performer is // outside of these areas. int can_heal = canPerformanceHeal(actor); //LOG("LOG_CHANNEL", "!!!!can_heal ->" + can_heal); if (can_heal == 0) return false; // Get the vital details on the performance int perf_index = getPerformanceType(actor); int buff_boost = performance.getPerformanceHealShockMod(perf_index); obj_id[] audience; // Get audience if (perf_type.equals(PERFORMANCE_TYPE_DANCE)) { audience = getPerformanceWatchersInRange(actor, PERFORMANCE_HEAL_RANGE); buff_boost = buff_boost * 5; } else if (perf_type.equals(PERFORMANCE_TYPE_MUSIC)) { audience = getPerformanceListenersInRange(actor, PERFORMANCE_HEAL_RANGE); buff_boost = (buff_boost * 5) / 2; } else { LOG("performance", "performance::performanceHeal -- bad perf_type"); return false; } for (int i = 0; i < audience.length; i++) { // Check for denial of service if (checkDenyService(actor, audience[i])) continue; // Provide some mind buffs if applicable. if (healing.canPerformanceMindBuff(actor, perf_type)) { if (getPerformanceType(audience[i]) == 0) { obj_id buff_target = utils.getObjIdScriptVar(actor, VAR_PERFORM_BUFF_TARGET); if (group.inSameGroup(actor, audience[i]) || utils.getObjIdScriptVar(actor, VAR_PERFORM_BUFF_TARGET) == audience[i]) { healing.applyPerformanceMindBuff(audience[i], actor, perf_type, buff_boost); } } } } */ return true; } boolean performanceSetPerformanceBuffTarget(obj_id actor, string target) { obj_id targetId = null; if (!isIdValid(targetId)) { performanceMessageToSelf(actor, null, SID_BUFF_INVALID_TARGET_SELF); return false; } return performanceSetPerformanceBuffTarget(actor, targetId); } boolean performanceSetPerformanceBuffTarget(obj_id actor, obj_id target) { if (!isIdValid(target)) { performanceMessageToSelf(actor, null, SID_BUFF_INVALID_TARGET_SELF); return false; } utils.setScriptVar(actor, VAR_PERFORM_BUFF_TARGET, target); performanceMessageToSelf(actor, target, SID_BUFF_SET_TARGET_SELF); performanceMessageToPerson(target, actor, target, SID_BUFF_SET_TARGET_OTHER); return true; } // ====================================================================== boolean applyPerformanceActionCost(obj_id actor, float modifier) { /* if (!isIdValid(actor)) return false; if (modifier <= 0) return false; int action = getAttrib(actor, ACTION); int perf_index = getPerformanceType(actor); int cost = (int)(getPerformanceActionCost(perf_index) * modifier); if(pet_lib.isDroidPet(actor)) cost /= 4; if (action < cost) return false; return drainAttributes(actor, cost, 0); */ return true; } float getPerformanceMistakeChance(obj_id actor) { /* // Calculate the chance for mistake int performanceIndex = getPerformanceType(actor); string req_skill_mod = dataTableGetString(DATATABLE_PERFORMANCE, performanceIndex - 1, DATATABLE_COL_REQ_SKILL); int req_skill_value = dataTableGetInt(DATATABLE_PERFORMANCE, performanceIndex - 1, DATATABLE_COL_REQ_SKILL_VALUE); int player_skill_mod = getSkillStatMod(actor, req_skill_mod); float mistake_chance = 15f - (player_skill_mod - req_skill_value); if (mistake_chance < 0) mistake_chance = 0; mistake_chance /= 4f; return mistake_chance; */ // remove mistakes for Entertaining return 0f; } boolean hasInspirationInstrumentUseBuff(obj_id actor, string instrument) { int col = 0; if(utils.hasScriptVar(actor, "buff.musician_inspiration.value")) col = 2; else if(utils.hasScriptVar(actor, "buff.entertainer_inspiration.value")) col = 1; else return false; string required = dataTableGetString("datatables/buff/entertainment_buff.iff", instrument, col); if(required.equals("none")) return true; return hasCommand(actor, required); } boolean hasInspirationDancePropUseBuff(obj_id actor, string prop) { int col = 0; if(utils.hasScriptVar(actor, "buff.dancer_inspiration.value")) col = 2; else if(utils.hasScriptVar(actor, "buff.entertainer_inspiration.value")) col = 1; else return false; string required = dataTableGetString("datatables/buff/entertainment_buff.iff", prop, col); if(required == null || required.equals("")) return false; if(required.equals("none")) return true; return hasCommand(actor, required); } boolean notShapechanged(obj_id actor) { //Can't while shapechanged. int shapechange = buff.getBuffOnTargetFromGroup(actor, "shapechange"); if(shapechange != 0) { sendSystemMessage(actor, SHAPECHANGE); return false; } return true; } boolean canDoPerformance(obj_id actor, int perf_index) { if (perf_index == 0) return false; if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); if(isIdValid(master)) return canDoPerformance(master, perf_index); else return false; } string req_skill_mod = dataTableGetString(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_SKILL); int req_skill_value = dataTableGetInt(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_SKILL_VALUE); int player_skill_mod = getSkillStatMod(actor, req_skill_mod); if (player_skill_mod < req_skill_value) return false; return true; } boolean canUseInstrument(obj_id actor, int perf_index) { //LOG ("performance", "Enter canUseInstrument"); if (perf_index == 0) { //LOG ("performance", "performance index is Zero"); return false; } if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); if(isIdValid(master)) return canUseInstrument(master, perf_index); else { //LOG ("performance", "is not a valid master - player"); return false; } } string req_ability = dataTableGetString(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_INSTRUMENT); //LOG ("performance", "Required instrument = " + req_ability); if (req_ability == null || req_ability.equals("")) { //LOG ("performance", "req_ability is NULL or NOTHING"); return false; } //in Feb 08 we added in hueable instruments. We need to remove the _hue at the end so we dont have duplicate //commands granted string[] splitAbility = split(req_ability, '_'); req_ability = splitAbility[0]; //LOG ("performance", "hasCommand(" + actor + "," + req_ability + ") " + hasCommand(actor, req_ability)); //LOG ("performance", "hasInspirationInstrumentUseBuff(actor, req_ability) " + hasInspirationInstrumentUseBuff(actor, req_ability)); if(hasCommand(actor, req_ability) || hasInspirationInstrumentUseBuff(actor, req_ability)) return true; //LOG ("performance", "returned false...hmm...end of function"); return false; } boolean canPerformSong(obj_id actor, int perf_index) { if (perf_index == 0) return false; if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); if(isIdValid(master)) return canPerformSong(master, perf_index); else return false; } string req_ability = dataTableGetString(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_SONG); LOG ("performance", "Required song = " + req_ability); if (req_ability == null || req_ability.equals("")) return false; //Dirge is taught from a Halloween reward and we need to do a profession/level check before allowing the song to be played. if (req_ability.indexOf("dirge") > -1) { if (!utils.isProfession(actor, utils.ENTERTAINER)) return false; else if (getLevel(actor) < 82) return false; } if (!hasCommand(actor, req_ability)) return false; return true; } boolean canPerformDance(obj_id actor, int perf_index) { if (perf_index == 0) return false; if(isHologramPerformer(actor)) { obj_id master = getMaster(actor); if(isIdValid(master)) return canPerformDance(master, perf_index); else return false; } if(utils.hasScriptVar(actor, "event.dance_party") ) { return true; } string req_ability = dataTableGetString(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_DANCE); LOG ("performance", "Required dance = " + req_ability); if (req_ability == null || req_ability.equals("")) return false; if (!hasCommand(actor, req_ability)) return false; return true; } boolean canPerformJuggle(obj_id actor, int perf_index) { if (perf_index == 0) return false; // Sure... why not if(isHologramPerformer(actor)) return true; string req_ability = dataTableGetString(DATATABLE_PERFORMANCE, perf_index - 1, DATATABLE_COL_REQ_JUGGLE); LOG ("performance", "Required juggle = " + req_ability); if (req_ability == null || req_ability.equals("")) return false; if (!hasCommand(actor, req_ability)) return false; return true; } /** * Returns true if object is a dance prop. * Dance props are of GOT_misc_instrument. * Object template name is also checked to distinguish them from musical instruments. * * @param object the obj_id of the object to check * @return true if object is a dance prop, else false */ boolean isValidDanceProp(obj_id object) { if (!isValidId(object)) return false; string template = getTemplateName(object); return isGameObjectTypeOf(object, GOT_misc_instrument) && template.startsWith("object/tangible/dance_prop/"); } /** * Returns false if object is a dance prop and player is not certified to use it. * * @param player the obj_id of the player to check * @param object the obj_id of the object to check * @return false if object is a dance prop and player is not certified to use it, else true. */ boolean isDancePropCertified(obj_id player, obj_id object) { if (!isValidDanceProp(object)) return true; if(hasObjVar(object, "nocert") && hasSkill(player, "social_entertainer_novice")) return true; // must be: object/tangible/dance_prop/prop_*_l.iff or prop_*_r.iff string template = getTemplateName(object); // convert to: prop_* string command = template.substring((template.lastIndexOf("/") + 1), template.lastIndexOf("_")); if(hasCommand(player, command)) return true; else if(hasInspirationDancePropUseBuff(player, command)) return true; return false; } // ====================================================================== int calcPerformanceXp(obj_id actor) { if (!isIdValid(actor)) return 0; if (!isPlayer(actor)) return 0; // Get the vital details on the performance int perf_index = getPerformanceType(actor); int flourish_xp = performance.getFlourishXpMod(perf_index); int base_xp = performance.getPerformanceBaseXp(perf_index); LOG ("entertainer_xp", "Performance Index = " + perf_index); LOG ("entertainer_xp", "Initial Flourish XP = " + flourish_xp); // Get all the band members int band_size = 1; obj_id[] band_members = new obj_id[20]; band_members[0] = actor; obj_id group = getGroupObject(actor); if (isIdValid(group)) { obj_id[] members = getGroupMemberIds(group); for (int i = 0; i < members.length; ++i) { if(pet_lib.isDroidPet(members[i]) || isHologramPerformer(members[i])) continue; if (getDistance(actor, members[i]) > PERFORMANCE_BAND_MEMBER_RANGE) continue; if (members[i] != actor && (hasScript(members[i], DANCE_HEARTBEAT_SCRIPT) || hasScript(members[i], MUSIC_HEARTBEAT_SCRIPT) || hasScript(members[i], JUGGLE_HEARTBEAT_SCRIPT))) { band_members[band_size] = members[i]; ++band_size; } } } // Count the band's audience ////////////////////////////////////////////////////////////////////////////////////////////////// // getBandAudienceInRange should be implemented in C++, change over when implemented ////////////////////////////////////////////////////////////////////////////////////////////////// obj_id[] audience = getBandAudienceInRange(band_members, band_size, PERFORMANCE_XP_RANGE); int audience_size = (audience.length - 1); if (audience_size < 0) audience_size = 0; if (audience_size > (PERFORM_XP_AUDIENCE_MAX_1 + PERFORM_XP_AUDIENCE_MAX_2)) audience_size = PERFORM_XP_AUDIENCE_MAX_1 + PERFORM_XP_AUDIENCE_MAX_2; // Retrieve the stored applause count and reset it int applause_count = getIntObjVar(actor, performance.VAR_PERFORM_APPLAUSE_COUNT); setObjVar(actor, performance.VAR_PERFORM_APPLAUSE_COUNT, 0); // Retrieve the flourish count and reset it int flourish_count = getIntObjVar(actor, performance.VAR_PERFORM_FLOURISH_COUNT); setObjVar(actor, performance.VAR_PERFORM_FLOURISH_COUNT, 0); setObjVar(actor, performance.VAR_PERFORM_FLOURISH_TOTAL, 0); LOG ("entertainer_xp", "Flourish Count = " + flourish_count); int flourishDec = (int)((float)flourish_xp / 6.0f); // Calculate the flourish xp flourish_xp *= flourish_count; int old_flourish_xp = getIntObjVar(actor, VAR_PERFORM_FLOURISH_XP); if (old_flourish_xp > flourish_xp) { flourish_xp = old_flourish_xp; if(flourish_xp > 0) flourish_xp -= flourishDec; if(flourish_xp < 0) flourish_xp = 0; } setObjVar(actor, VAR_PERFORM_FLOURISH_XP, flourish_xp); // Calculate the XP to award int xp_amount = base_xp + flourish_xp; LOG ("entertainer_xp", "XP Amount = " + xp_amount + ", (Base XP: " + base_xp + " + (Flourish XP: " + flourish_xp + "))"); float band_mod = ((band_size - 1) / ((float)PERFORM_XP_GROUP_MAX)) * PERFORM_XP_GROUP_MOD; float applause_mod = applause_count / 100f; LOG ("entertainer_xp", "Band Mod = " + band_mod); LOG ("entertainer_xp", "Applaues Mod = " + applause_mod); float audience_mod = (float)audience_size / 50f; LOG ("entertainer_xp", "Audience Mod = " + audience_mod); float xp_mod = 1f + band_mod + audience_mod + applause_mod; //LOG ("entertainer_xp", "XP Mod = " + xp_mod + ", (1 + Band Mod: " + band_mod + " + Audience Mod: " + audience_mod + " + Applause Mod: " + applause_mod + ")"); xp_amount = (int) (xp_amount * xp_mod); LOG ("entertainer_xp", "XP Mod = " + xp_mod); LOG ("entertainer_xp", "Total XP = " + xp_amount); return xp_amount; } ////////////////////////////////////////////////////////////////////////////////////////////////// obj_id[] getBandAudienceInRange(obj_id[] band_members, int band_size, float range) { resizeable obj_id[] audience = new obj_id[0]; for (int i = 0; i < band_size; i++) { obj_id[] member_audience; if (isIdValid(band_members[i])) { if (hasScript(band_members[i], DANCE_HEARTBEAT_SCRIPT) || hasScript(band_members[i], JUGGLE_HEARTBEAT_SCRIPT)) { member_audience = getPerformanceWatchersInRange(band_members[i], range); } else { member_audience = getPerformanceListenersInRange(band_members[i], range); } if (member_audience != null && member_audience.length > 0) { for (int j = 0; j < member_audience.length; j++) { if (!utils.isElementInArray(audience, member_audience[j])) { if (isIdValid(member_audience[j])) { if (!checkDenyService(band_members[i], member_audience[j])) { utils.addElement(audience, member_audience[j]); } } } } } } } return audience; } // ====================================================================== void denyService(obj_id player, obj_id target) { if (checkDenyService(player, target)) { removeDenyService(player, target); } else { addDenyService(player, target); } } void addDenyService(obj_id player, obj_id target) { if(utils.hasScriptVar(target, VAR_PERFORM_PAY_AGREE)) { obj_id watched = getPerformanceWatchTarget(target); obj_id listened = getPerformanceListenTarget(target); if((isIdValid(watched) && watched == player) || (isIdValid(listened) && listened == player)) { sendSystemMessage(player, SID_DENY_SERVICE_COVER_CHARGE); return; } } resizeable obj_id[] denyServiceList = utils.getResizeableObjIdBatchScriptVar(player, "performance.denyService"); if (denyServiceList == null) denyServiceList = new Vector(); utils.addElement(denyServiceList, target); utils.setBatchScriptVar(player, "performance.denyService", denyServiceList); performanceMessageToSelf(player, target, SID_DENY_SERVICE_ADD_SELF); performanceMessageToPerson(target, player, target, SID_DENY_SERVICE_ADD_OTHER); } void removeDenyService(obj_id player, obj_id target) { resizeable obj_id[] denyServiceList = utils.getResizeableObjIdBatchScriptVar(player, "performance.denyService"); if (denyServiceList == null) return; utils.removeElement(denyServiceList, target); if (denyServiceList.length == 0) { utils.removeBatchScriptVar(player, "performance.denyService"); } else { utils.setBatchScriptVar(player, "performance.denyService", denyServiceList); } performanceMessageToSelf(player, target, SID_DENY_SERVICE_REMOVE_SELF); performanceMessageToPerson(target, player, target, SID_DENY_SERVICE_REMOVE_OTHER); } boolean checkDenyService(obj_id player, obj_id target) { resizeable obj_id[] denyServiceList = utils.getResizeableObjIdBatchScriptVar(player, "performance.denyService"); if (denyServiceList == null) return false; return utils.isElementInArray(denyServiceList, target); } // ====================================================================== boolean displayAvailableMusic(obj_id actor, boolean band, boolean changeMusic) { if (!isIdValid(actor)) return false; if (!notShapechanged(actor)) { return false; } int instrument_equipped = getInstrumentAudioId(actor); if (instrument_equipped == 0) { performanceMessageToSelf(actor, null, SID_MUSIC_NO_INSTRUMENT); return true; } resizeable string[] available_music = new string[0]; int num_items = dataTableGetNumRows(DATATABLE_PERFORMANCE); for (int i = 0; i < num_items; i++) { dictionary row = dataTableGetRow(DATATABLE_PERFORMANCE, i); int type = row.getInt("type"); if (type == ##"music") { // If the player has an instrument, only consider entries that use it. int instrument_id = row.getInt("instrumentAudioId"); if (instrument_equipped != instrument_id) continue; string name = row.getString("performanceName"); // Check to see that the player has the skill to perform the song. if (canPerformSong(actor, i + 1)) { name = name.substring(0,1).toUpperCase() + name.substring(1).toLowerCase(); available_music = utils.addElement(available_music, name); } } } // Display the results if (available_music.length > 0) { sui.listbox(actor, actor, "@performance:select_song", sui.OK_CANCEL, "@performance:available_songs", available_music, "msgSongSelected"); // attach the performance script to the player so that the sui message handler can be called. if (!hasScript(actor, PERFORMANCE_SELECT)) attachScript(actor, PERFORMANCE_SELECT); // store options on player. setObjVar(actor, VAR_AVAILABLE_PERFORMANCES, available_music); setObjVar(actor, VAR_SELECT_MUSIC_BAND, band); setObjVar(actor, VAR_SELECT_MUSIC_CHANGE, changeMusic); return true; } return false; } // ====================================================================== boolean displayAvailableDances(obj_id actor, boolean changeDance) { if (!isIdValid(actor)) return false; if (hasObjVar(actor, VAR_AVAILABLE_PERFORMANCES)) return false; if (!notShapechanged(actor)) { return false; } resizeable string[] available_dances = new string[0]; int num_items = dataTableGetNumRows(DATATABLE_PERFORMANCE); for (int i = 0; i < num_items; i++) { dictionary row = dataTableGetRow(DATATABLE_PERFORMANCE, i); int type = row.getInt("type"); if (type == ##"dance") { // Check to see that the player has the skill to perform the song. string name = row.getString("performanceName"); if (canPerformDance(actor, i + 1)) { name = name.substring(0,1).toUpperCase() + name.substring(1).toLowerCase(); available_dances = utils.addElement(available_dances, name); } } } // Display the results if (available_dances.length > 0) { sui.listbox(actor, actor, "@performance:select_dance", sui.OK_CANCEL, "@performance:available_dances", available_dances, "msgDanceSelected"); // attach the performance script to the player so that the sui message handler can be called. if (!hasScript(actor, PERFORMANCE_SELECT)) attachScript(actor, PERFORMANCE_SELECT); // store options on player. setObjVar(actor, VAR_AVAILABLE_PERFORMANCES, available_dances); if (changeDance) setObjVar(actor, VAR_SELECT_DANCE_CHANGE, 1); return true; } return false; } // ====================================================================== boolean displayAvailableJuggles(obj_id actor, boolean changeJuggle) { if (!isIdValid(actor)) return false; if (hasObjVar(actor, VAR_AVAILABLE_PERFORMANCES)) return false; if (!notShapechanged(actor)) { return false; } resizeable string[] available_juggles = new string[0]; int num_items = dataTableGetNumRows(DATATABLE_PERFORMANCE); for (int i = 0; i < num_items; i++) { dictionary row = dataTableGetRow(DATATABLE_PERFORMANCE, i); int type = row.getInt("type"); if (type == ##"juggle") { // Check to see that the player has the skill to perform the song. string name = row.getString("performanceName"); if (canPerformJuggle(actor, i + 1)) { name = name.substring(0,1).toUpperCase() + name.substring(1).toLowerCase(); available_juggles = utils.addElement(available_juggles, name); } } } // Display the results if (available_juggles.length > 0) { sui.listbox(actor, actor, "@performance:select_juggs", sui.OK_CANCEL, "@performance:available_juggs", available_juggles, "msgJuggleSelected"); // attach the performance script to the player so that the sui message handler can be called. if (!hasScript(actor, PERFORMANCE_SELECT)) attachScript(actor, PERFORMANCE_SELECT); // store options on player. setObjVar(actor, VAR_AVAILABLE_PERFORMANCES, available_juggles); if (changeJuggle) setObjVar(actor, VAR_SELECT_JUGGLE_CHANGE, 1); return true; } return false; } // ====================================================================== // returns 0 if can't heal at all, 1 if can heal wound, 2 if can heal wound and shockwound. int canPerformanceHeal(obj_id actor) { if(pet_lib.isDroidPet(actor) || isHologramPerformer(actor)) return 0; if(!utils.isProfession(actor, utils.ENTERTAINER)) return 0; // check to see if the player is in a valid entertainment area location loc = getLocation(actor); if (isIdValid(loc.cell)) { obj_id building = getTopMostContainer(loc.cell); if (!hasObjVar(building, "healing.canhealshock") && !hasObjVar(loc.cell, "healing.canhealshock")) return 0; return 2; } if(camping.isInEntertainmentCamp(actor)) return 2; // Check for theatre region region[] regs = getRegionsWithGeographicalAtPoint(getLocation(actor), regions.GEO_THEATER); if (regs != null && regs.length > 0) return 2; //TODO Improv int improv = (int)getSkillStatisticModifier(actor, "expertise_en_improv"); if (improv == 1) { return 3; } return 0; } // ====================================================================== boolean isInRightBuilding(obj_id objPlayer, obj_id objBuilding) { location locTest = getLocation(objPlayer); if (isIdValid(locTest.cell)) { obj_id objOwner = getTopMostContainer(locTest.cell); if (objBuilding == objOwner) return true; } return false; } void checkAndIncrementEntertainerMissions(obj_id objPlayer, string strType) { if (hasObjVar (objPlayer, "newbie_handoff.mission.gig")) { incrementNewbieHandoffEntertainerMissions(objPlayer, strType); } LOG("missions", "checking for entertainer missions"); obj_id[] objMissions = getMissionObjects(objPlayer); if(objMissions==null) { LOG("missions", "no missions found"); return; } int intI = 0; while(intI=intDuration) { messageTo(objMissions[intI], "entertainerSuccess", null, 0, true); // spawner timer has started } } } intI = intI+1; } } void stopEntertainerMissionTracking(obj_id objPlayer, string strType) { if (hasObjVar (objPlayer, "newbie_handoff.mission.gig")) { stopNewbieHandoffEntertainerMissionTracking(objPlayer, strType); } obj_id[] objMissions = getMissionObjects(objPlayer); if(objMissions == null) { return; } int intI = 0; while(intI < objMissions.length) { obj_id objMissionData = objMissions[intI]; if(!isIdValid(objMissionData)) { LOG("DESIGNER_FATAL", "Mission object with null mission data, id is "+objMissions[intI]+" player is "+objPlayer); return; } string strMissionType = getMissionType(objMissionData); if(strMissionType == null) { LOG("DESIGNER_FATAL", "strMissionType is null for "+objMissionData+" and player is "+objPlayer+" and objMission is "+objMissions[intI]); return; } if(strMissionType == strType) { if(hasObjVar(objMissions[intI], "intStartTime")) { removeObjVar(objMissions[intI], "intStartTime"); } } intI++; } } void incrementNewbieHandoffEntertainerMissions(obj_id player, string type) { string missionType = getStringObjVar( player, "newbie_handoff.mission.gig.type" ); LOG("newbie_gig_mission", "Current mission type: "+missionType+", current performance type: "+type); if ( type.equals(missionType) ) { obj_id building = getObjIdObjVar( player, "newbie_handoff.mission.gig.obj" ); LOG("newbie_gig_mission", "Checking to see if in correct building. - "+building); if ( isInRightBuilding(player, building) ) { int duration = getIntObjVar( player, "newbie_handoff.mission.gig.duration" ); int curTime = getGameTime(); int start = curTime; if ( hasObjVar(player, "newbie_handoff.mission.gig.start") ) { start = getIntObjVar( player, "newbie_handoff.mission.gig.start" ); LOG("newbie_gig_mission", "Getting mission start time "+start); } else { setObjVar( player, "newbie_handoff.mission.gig.start", start); LOG("newbie_gig_mission", "Initializing mission start time "+start); return; } int elapsedTime = curTime - start; if ( elapsedTime >= duration ) { LOG("newbie_gig_mission", "Mission Complete"); messageTo( player, "missionGigComplete", null, 0, true ); } } } } void stopNewbieHandoffEntertainerMissionTracking(obj_id player, string type) { if ( hasObjVar(player, "newbie_handoff.mission.gig.start") ) { LOG("newbie_gig_mission", "Removing time tracking objvar"); removeObjVar( player, "newbie_handoff.mission.gig.start" ); } } // ---------------------------------------------------------------------- void startJuggling(obj_id actor, string juggleName) { if (juggleName == null || juggleName.length() < 1) { displayAvailableJuggles(actor, false); return; } if (getPerformanceType(actor) != 0) { performanceMessageToSelf(actor, null, SID_ALREADY_PERFORMING_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"juggle", juggleName, 0); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_JUGGLE_UNKNOWN_SELF); return; } if (!notShapechanged(actor)) { return; } // Check to see if the player has the skill to perform the selected dance. if (!canPerformJuggle(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_JUGGLE_LACK_SKILL_SELF); return; } // start the performance performanceMessageToSelf(actor, null, SID_JUGGLE_START_SELF); performanceMessageToWatchers(actor, null, SID_JUGGLE_START_OTHER); dictionary params; int startTime = getGameTime(); setPerformanceType(actor, performanceIndex); setPerformanceStartTime(actor, startTime); //Let the actor watch himself so that he gets healing effects setPerformanceWatchTarget(actor, actor); attachScript(actor, JUGGLE_HEARTBEAT_SCRIPT); sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_START, PERFORMANCE_TYPE_JUGGLE); params = new dictionary(); params.put("performer", actor); broadcastMessage("handlePerformerStartPerforming", params); params = new dictionary(); params.put("performanceIndex", performanceIndex); params.put("sequence", 0); messageTo(actor, "OnPulse", params, PERFORMANCE_HEARTBEAT_TIME, false); } // ---------------------------------------------------------------------- void stopJuggling(obj_id actor) { if (hasScript(actor, JUGGLE_HEARTBEAT_SCRIPT)) { // Not using this message anymore ai now subscribe to "handlePerformerStopPerforming" //sendNpcsEntertainmentMessage(actor, NPC_ENTERTAINMENT_MESSAGE_STOP, PERFORMANCE_TYPE_JUGGLE); dictionary params = new dictionary(); params.put("performer", actor); params.put("check", "musician"); broadcastMessage("handlePerformerStopPerforming", params); messageTo(actor, "OnPerformanceEnd", null, 0.0f, false); setPerformanceType(actor, 0); setPerformanceStartTime(actor, 0); performanceMessageToSelf(actor, null, SID_JUGGLE_STOP_SELF); performanceMessageToWatchers(actor, null, SID_JUGGLE_STOP_OTHER); } else { if (hasObjVar(actor, performance.VAR_PERFORM)) { removeObjVar(actor, performance.VAR_PERFORM); } performanceMessageToSelf(actor, null, SID_JUGGLE_NOT_PERFORMING); } } // ---------------------------------------------------------------------- void changeJuggle(obj_id actor, string juggleName) { if (juggleName == null || juggleName.length() < 1) { displayAvailableJuggles(actor, true); return; } if (!hasScript(actor, JUGGLE_HEARTBEAT_SCRIPT)) { performanceMessageToSelf(actor, null, SID_JUGGLE_MUST_BE_PERFORMING_SELF); return; } int performanceIndex = lookupPerformanceIndex(##"juggle", juggleName, 0); if (performanceIndex == 0) { performanceMessageToSelf(actor, null, SID_JUGGLE_UNKNOWN_SELF); return; } if (!notShapechanged(actor)) { return; } // Check to see if the player has the skill to perform the selected dance. if (!canPerformJuggle(actor, performanceIndex)) { performanceMessageToSelf(actor, null, SID_JUGGLE_LACK_SKILL_SELF); return; } setPerformanceType(actor, performanceIndex); queueCommand(actor, ##"showDanceVisuals", null, "1", COMMAND_PRIORITY_IMMEDIATE); } // ---------------------------------------------------------------------- void openInspireMenu(obj_id self, obj_id target) { if(utils.hasScriptVar(self, VAR_BUFF_SUI)) { int pidClose = utils.getIntScriptVar(self, VAR_BUFF_SUI); forceCloseSUIPage(pidClose); } if(!utils.isProfession(self, utils.ENTERTAINER)) return; Vector dsrc = new Vector(); Vector list = new Vector(); for(int i = 0; i < INSPIRATION_BUFF_ENTERTAINER.length; i++) { dsrc.addElement("@performance:" + INSPIRATION_BUFF_ENTERTAINER[i]); list.addElement(INSPIRATION_BUFF_ENTERTAINER[i]); } string type = ""; if(hasScript(self, DANCE_HEARTBEAT_SCRIPT)) { obj_id watched = getPerformanceWatchTarget(target); if(watched != self) { sendSystemMessage(self, new string_id("performance", "insp_buff_must_watch")); return; } for(int i = 0; i < INSPIRATION_BUFF_DANCER.length; i++) { dsrc.addElement("@performance:" + INSPIRATION_BUFF_DANCER[i]); list.addElement(INSPIRATION_BUFF_DANCER[i]); } } else if(hasScript(self, MUSIC_HEARTBEAT_SCRIPT)) { obj_id listened = getPerformanceListenTarget(target); if(listened != self) { sendSystemMessage(self, new string_id("performance", "insp_buff_must_listen")); return; } for(int i = 0; i < INSPIRATION_BUFF_MUSICIAN.length; i++) { dsrc.addElement("@performance:" + INSPIRATION_BUFF_MUSICIAN[i]); list.addElement(INSPIRATION_BUFF_MUSICIAN[i]); } } else { sendSystemMessage(self, new string_id("performance", "insp_buff_must_perform")); return; } string prompt = "@performance:inspire_menu_prompt " + getName(target); prompt += "\n\n"; prompt += "@performance:inspire_menu_prompt2"; string title = "@performance:inspire_menu_title"; int pid = sui.listbox(self, self, prompt, sui.OK_CANCEL, title, dsrc, "handleInspireMenu"); if(pid >= 0) { utils.setScriptVar(self, VAR_BUFF_LIST, utils.toStaticStringArray(list)); utils.setScriptVar(self, VAR_BUFF_TARGET, target); utils.setScriptVar(self, VAR_BUFF_SUI, pid); } } // ---------------------------------------------------------------------- boolean hasMaxHolo(obj_id actor) { if(!isIdValid(actor)) return true; if (utils.hasScriptVar(actor, "currentHolo")) { int holoPets = utils.getIntScriptVar(actor, "currentHolo"); int holoMod = (int)getSkillStatisticModifier(actor, "expertise_en_holographic_additional_backup"); int maxHoloAllowed = 1; maxHoloAllowed += holoMod; if (holoPets >= maxHoloAllowed) { return true; } } return false; } void holographicCleanup(obj_id actor) { obj_id holoDelete = null; if (utils.hasScriptVar(actor, "holoId1")) { holoDelete = utils.getObjIdScriptVar(actor, "holoId1"); if (exists(holoDelete)) { destroyObject(holoDelete); } } if (utils.hasScriptVar(actor, "holoId2")) { holoDelete = utils.getObjIdScriptVar(actor, "holoId2"); if (exists(holoDelete)) { destroyObject(holoDelete); } } if (utils.hasScriptVar(actor, "holoId3")) { holoDelete = utils.getObjIdScriptVar(actor, "holoId3"); if (exists(holoDelete)) { destroyObject(holoDelete); } } utils.removeScriptVar(actor, "currentHolo"); utils.removeScriptVar(actor, "holoMessageTime"); utils.removeScriptVar(actor, "holoId1"); utils.removeScriptVar(actor, "holoId2"); utils.removeScriptVar(actor, "holoId3"); sendSystemMessage(actor, new string_id("spam", "holo_despawned")); return; } boolean createHolographicBackup(obj_id actor) { if(!isIdValid(actor)) return false; if (group.isGrouped(actor)) { obj_id groupId = getGroupObject(actor); obj_id[] groupMembers = getGroupMemberIds( groupId ); if (groupMembers.length == 8) { sendSystemMessage(actor, new string_id("spam", "holo_group_full")); return false; } obj_id groupLeaderId = getGroupLeaderId( groupId ); if (groupLeaderId != actor) { sendSystemMessage(actor, new string_id("spam", "holo_not_leader")); return false; } } location myLoc = getLocation(actor); int species = getSpecies(actor); int gender = getGender(actor); string template = "object/mobile/hologram/"; string speciesString = "human"; string genderString = "male"; switch(species) { case SPECIES_RODIAN: speciesString = "rodian"; break; case SPECIES_TRANDOSHAN: speciesString = "trandoshan"; break; case SPECIES_MON_CALAMARI: speciesString = "moncal"; break; case SPECIES_WOOKIEE: speciesString = "wookiee"; break; case SPECIES_BOTHAN: speciesString = "bothan"; break; case SPECIES_TWILEK: speciesString = "twilek"; break; case SPECIES_ZABRAK: speciesString = "zabrak"; break; case SPECIES_ITHORIAN: speciesString = "ithorian"; break; case SPECIES_SULLUSTAN: speciesString = "sullustan"; break; } if(gender == GENDER_FEMALE) genderString = "female"; template += speciesString + "_" + genderString + ".iff"; obj_id hologram = createObject(template, myLoc); if(isIdValid(hologram)) { int holoPets = 1; if (utils.hasScriptVar(actor, "currentHolo")) { holoPets = utils.getIntScriptVar(actor, "currentHolo"); holoPets = holoPets +1; utils.setScriptVar(actor, "currentHolo", holoPets); } else { utils.setScriptVar(actor, "currentHolo", holoPets); } int intTime = getGameTime(); utils.setScriptVar(actor, "holoMessageTime", intTime); utils.setScriptVar(actor, "holoId" +holoPets, hologram); dictionary msgTimer = new dictionary(); msgTimer.put("holoMessageTime", intTime); messageTo(actor, "handleHoloTimeout", msgTimer, 3600, false); setMaster(hologram, actor); setScale(hologram, getScale(actor)); setYaw(hologram, getYaw(actor)); setHologramType(hologram, HOLOGRAM_TYPE1_QUALITY4); setName(hologram, "Hologram"); setInvulnerable(hologram, true); custom_var[] var_list = getAllCustomVars(actor); if(var_list != null && var_list.length > 0) { for(int i = 0; i < var_list.length; i++) { ranged_int_custom_var ricv = (ranged_int_custom_var)var_list[i]; string var = ricv.getVarName(); int value = ricv.getValue(); if(value != 0) { setRangedIntCustomVarValue(hologram, var, value); } // debugSpeakMsg(actor, "var=[" + var + "] value=[" + value + "]"); } } // set the hologram skin color to white to resolve facial corruption issues when the hologram shader is used setPalcolorCustomVarClosestColor(hologram,"/shared_owner/index_color_skin", 255,255,255,255); obj_id[] contents = getAllWornItems(actor, false); utils.setObjVar(hologram, "hologram_performer", 1); // objvar checked in c code to allow transfer of biolinked items to holograms if(contents != null && contents.length > 0) { for(int i = 0; i < contents.length; i++) { if(isIdValid(contents[i])) { if(getContainerType(contents[i]) == 0) { // No need to dupe invisible items. if(getGameObjectType(contents[i]) == GOT_misc_appearance_only_invisible) continue; if (!getTemplateName(contents[i]).endsWith("player.iff")) { createObject(getTemplateName(contents[i]), hologram, ""); } } } } } setMaster(hologram, actor); attachScript(hologram, "systems.skills.performance.holographic_backup"); utils.setScriptVar(hologram, "hologram_performer", 1); queueCommand(actor, ##"invite", hologram, "", COMMAND_PRIORITY_DEFAULT); messageTo(hologram, "handleGroupInvitation", null, 2f, false); return true; } return false; }