Files
dsrc/sku.0/sys.server/compiled/game/script/library/performance.scriptlib
T
2013-09-10 23:17:15 -07:00

4458 lines
135 KiB
Plaintext

// ======================================================================
//
// performance.scriptlib - music/dancing script library
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
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<objMissions.length)
{
obj_id objMissionData = objMissions[intI];
string strMissionType = getMissionType(objMissionData);
LOG("missions", "strMissionType is "+strMissionType);
if(strMissionType==strType)
{
obj_id objBuilding = getObjIdObjVar(objMissionData, "objBuilding");
LOG("mission", "building is "+objBuilding);
if(isInRightBuilding(objPlayer, objBuilding))
{
// VALID
// do we have a timestamp, if so, compare to gametime, if not, contine
// if we don't have a timestamp, set it and continue
int intDuration = getIntObjVar(objMissionData, "intTime"); // how long do i need to entertain
int intGameTime = getGameTime();
int intStartTime = intGameTime;
if(hasObjVar(objMissions[intI], "intStartTime"))
{
intStartTime = getIntObjVar(objMissions[intI], "intStartTime");
}
else
{
setObjVar(objMissions[intI], "intStartTime", intStartTime); // timestamp
return;
}
int intElapsedTime = intGameTime - intStartTime;
LOG("missions", "intElapsedTime is "+intElapsedTime);
if(intElapsedTime>=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;
}