#using scripts\core\_multi_extracam; #using scripts\codescripts\struct; #using scripts\shared\abilities\gadgets\_gadget_camo_render; #using scripts\shared\animation_shared; #using scripts\shared\duplicaterender_mgr; #using scripts\shared\end_game_taunts; #using scripts\shared\filter_shared; #using scripts\shared\scene_shared; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\array_shared; #namespace character_customization; #using_animtree("all_player"); function autoexec __init__sytem__() { system::register("character_customization",&__init__,undefined,undefined); } /////////////////////////////////////////////////////////////////////////// // SETUP /////////////////////////////////////////////////////////////////////////// function __init__() { level.extra_cam_render_hero_func_callback = &process_character_extracam_request; level.extra_cam_render_lobby_client_hero_func_callback = &process_lobby_client_character_extracam_request; level.extra_cam_render_current_hero_headshot_func_callback = &process_current_hero_headshot_extracam_request; level.extra_cam_render_outfit_preview_func_callback = &process_outfit_preview_extracam_request; level.extra_cam_render_character_body_item_func_callback = &process_character_body_item_extracam_request; level.extra_cam_render_character_helmet_item_func_callback = &process_character_helmet_item_extracam_request; level.extra_cam_render_character_head_item_func_callback = &process_character_head_item_extracam_request; level.model_type_bones = associativearray( "helmet", "", "head", "" ); if(!isdefined(level.liveCCData))level.liveCCData=[]; if(!isdefined(level.custom_characters))level.custom_characters=[]; if(!isdefined(level.extra_cam_hero_data))level.extra_cam_hero_data=[]; if(!isdefined(level.extra_cam_lobby_client_hero_data))level.extra_cam_lobby_client_hero_data=[]; if(!isdefined(level.extra_cam_headshot_hero_data))level.extra_cam_headshot_hero_data=[]; if(!isdefined(level.extra_cam_outfit_preview_data))level.extra_cam_outfit_preview_data=[]; level.characterCustomizationSetup = &localClientConnect; } function localClientConnect( localClientNum ) { // setup our live and static characters level.liveCCData[localClientNum] = setup_live_character_customization_target( localClientNum ); if( IsDefined( level.liveCCData[localClientNum] ) ) { setup_character_streaming( level.liveCCData[localClientNum] ); } level.staticCCData = setup_static_character_customization_target( localClientNum ); } function create_character_data_struct( characterModel, localClientNum, alt_render_mode = true ) { if ( !isdefined( characterModel ) ) { return undefined; } if(!isdefined(level.custom_characters[localClientNum]))level.custom_characters[localClientNum]=[]; if ( isdefined( level.custom_characters[localClientNum][characterModel.targetname] ) ) { return level.custom_characters[localClientNum][characterModel.targetname]; } data_struct = SpawnStruct(); level.custom_characters[localClientNum][characterModel.targetname] = data_struct; // models data_struct.characterModel = characterModel; data_struct.attached_model_anims = array(); data_struct.attached_models = array(); data_struct.attached_entities = array(); data_struct.origin = characterModel.origin; data_struct.angles = characterModel.angles; // indices data_struct.characterIndex = 0; data_struct.characterMode = 3; data_struct.splitScreenClient = undefined; data_struct.bodyIndex = 0; data_struct.bodyColors = array( 0, 0, 0 ); data_struct.helmetIndex = 0; data_struct.helmetColors = array( 0, 0, 0 ); data_struct.headIndex = 0; data_struct.align_target = undefined; data_struct.currentAnimation = undefined; data_struct.currentScene = undefined; // render options data_struct.body_render_options = GetCharacterBodyRenderOptions( 0, 0, 0, 0, 0 ); data_struct.helmet_render_options = GetCharacterHelmetRenderOptions( 0, 0, 0, 0, 0 ); data_struct.head_render_options = GetCharacterHeadRenderOptions( 0 ); data_struct.mode_render_options = GetCharacterModeRenderOptions( 0 ); data_struct.alt_render_mode = alt_render_mode; // menu options data_struct.useFrozenMomentAnim = false; data_struct.frozenMomentStyle = "weapon"; data_struct.show_helmets = true; data_struct.allow_showcase_weapons = false; data_struct.force_prologue_body = false; if ( SessionModeIsCampaignGame() ) { highestMapReached = GetDStat( localClientNum, "highestMapReached" ); data_struct.force_prologue_body = ( !isdefined(highestMapReached) || highestMapReached == 0 ) && GetDvarString( "mapname" ) == "core_frontend"; } characterModel SetHighDetail( true, data_struct.alt_render_mode ); return data_struct; } function handle_forced_streaming( game_mode ) { return; // MJD - disable all forcing heroes = GetHeroes( game_mode ); foreach( hero in heroes ) { bodies = GetHeroBodyModelIndices( hero, game_mode ); helmets = GetHeroHelmetModelIndices( hero, game_mode ); foreach( helmet in helmets ) { ForceStreamXModel( helmet, 8, -1 ); } foreach( body in bodies ) { ForceStreamXModel( body, 8, -1 ); } } heads = GetHeroHeadModelIndices( game_mode ); foreach( head in heads ) { ForceStreamXModel( head, 8, -1 ); } } /////////////////////////////////////////////////////////////////////////// // UTILITY /////////////////////////////////////////////////////////////////////////// // supported "params" fields: align_struct, anim_name, weapon_left, weapon_right, scene, extracam_data function loadEquippedCharacterOnModel( localClientNum, data_struct, characterIndex, params ) { assert( isdefined( data_struct ) ); data_lcn = (isdefined(data_struct.splitScreenClient)?data_struct.splitScreenClient:localClientNum); if( !isdefined( characterIndex ) ) { characterIndex = GetEquippedHeroIndex( data_lcn, params.sessionMode ); } defaultIndex = undefined; if ( ( isdefined( params.isDefaultHero ) && params.isDefaultHero ) ) { defaultIndex = 0; } set_character( data_struct, characterIndex ); characterMode = params.sessionMode; set_character_mode( data_struct, characterMode ); body = get_character_body( data_lcn, characterMode, characterIndex, params.extracam_data ); bodyColors = get_character_body_colors( data_lcn, characterMode, characterIndex, body, params.extracam_data ); set_body( data_struct, characterMode, characterIndex, body, bodyColors ); head = character_customization::get_character_head( data_lcn, characterMode, params.extracam_data ); set_head( data_struct, characterMode, head ); helmet = get_character_helmet( data_lcn, characterMode, characterIndex, params.extracam_data ); helmetColors = get_character_helmet_colors( data_lcn, characterMode, data_struct.characterIndex, helmet, params.extracam_data ); set_helmet( data_struct, characterMode, characterIndex, helmet, helmetColors ); if ( ( isdefined( data_struct.allow_showcase_weapons ) && data_struct.allow_showcase_weapons ) ) { showcaseWeapon = get_character_showcase_weapon( data_lcn, characterMode, characterIndex, params.extracam_data ); set_showcase_weapon( data_struct, characterMode, data_lcn, undefined, characterIndex, showcaseWeapon.weaponName, showcaseWeapon.attachmentInfo, showcaseWeapon.weaponRenderOptions, false, true ); } return update( localClientNum, data_struct, params ); } #using_animtree("generic"); function update_model_attachment( localClientNum, data_struct, attached_model, slot, model_anim, model_intro_anim, force_update ) { assert( isdefined( data_struct.attached_models ) ); assert( isdefined( data_struct.attached_model_anims ) ); assert( isdefined( level.model_type_bones ) ); if ( force_update || attached_model !== data_struct.attached_models[slot] || model_anim !== data_struct.attached_model_anims[slot] ) { bone = slot; if ( isdefined( level.model_type_bones[slot] ) ) { bone = level.model_type_bones[slot]; } assert( isdefined( bone ) ); if ( isdefined( data_struct.attached_models[slot] ) ) { if ( isDefined(data_struct.attached_entities[slot]) ) { data_struct.attached_entities[slot] Unlink(); data_struct.attached_entities[slot] Delete(); data_struct.attached_entities[slot] = undefined; } else { if( data_struct.characterModel IsAttached( data_struct.attached_models[slot], bone ) ) { data_struct.characterModel Detach( data_struct.attached_models[slot], bone ); } } data_struct.attached_models[slot] = undefined; } data_struct.attached_models[slot] = attached_model; if ( isdefined( data_struct.attached_models[slot] ) ) { if ( isDefined(model_anim) ) { ent = Spawn( localClientNum, data_struct.characterModel.origin, "script_model" ); ent SetHighDetail( true, data_struct.alt_render_mode ); data_struct.attached_entities[slot] = ent; ent SetModel( data_struct.attached_models[slot] ); if ( !ent HasAnimTree() ) { ent UseAnimTree( #animtree ); } ent.origin = data_struct.characterModel.origin; ent.angles = data_struct.characterModel.angles; ent.chosenOrigin = ent.origin; ent.chosenAngles = ent.angles; ent thread play_intro_and_animation( model_intro_anim, model_anim, true ); } else { if ( !data_struct.characterModel IsAttached( data_struct.attached_models[slot], bone ) ) { data_struct.characterModel Attach( data_struct.attached_models[slot], bone ); } } data_struct.attached_model_anims[slot] = model_anim; } } // Need to set the customization since it could have changed without changing attachments. if ( isDefined( data_struct.attached_entities[slot] ) ) data_struct.attached_entities[slot] SetBodyRenderOptions( data_struct.mode_render_options, data_struct.body_render_options, data_struct.helmet_render_options, data_struct.head_render_options ); } function set_character( data_struct, characterIndex ) { data_struct.characterIndex = characterIndex; } function set_character_mode( data_struct, characterMode ) { assert( isdefined( characterMode ) ); data_struct.characterMode = characterMode; data_struct.mode_render_options = GetCharacterModeRenderOptions( characterMode ); } function set_body( data_struct, mode, characterIndex, bodyIndex, bodyColors ) { assert( isdefined( mode ) ); assert( mode != 3 ); if ( mode == 2 && ( isdefined( data_struct.force_prologue_body ) && data_struct.force_prologue_body ) ) { bodyIndex = 1; // force pbt_cp_male_body_01_prologue or pbt_cp_female_body_01_prologue since we're not cyber yet } data_struct.bodyIndex = bodyIndex; data_struct.bodyModel = GetCharacterBodyModel( characterIndex, bodyIndex, mode ); if( isdefined( data_struct.bodyModel ) ) { data_struct.characterModel SetModel( data_struct.bodyModel ); } if( isdefined( bodyColors ) ) { set_body_colors( data_struct, mode, bodyColors ); } render_options = GetCharacterBodyRenderOptions( data_struct.characterIndex, data_struct.bodyIndex, data_struct.bodyColors[0], data_struct.bodyColors[1], data_struct.bodyColors[2] ); data_struct.body_render_options = render_options; } function set_body_colors( data_struct, mode, bodyColors ) { for( i = 0; i < bodyColors.size && i < bodyColors.size; i++ ) { set_body_color( data_struct, i, bodyColors[ i ] ); } } function set_body_color( data_struct, colorSlot, colorIndex ) { data_struct.bodyColors[ colorSlot ] = colorIndex; render_options = GetCharacterBodyRenderOptions( data_struct.characterIndex, data_struct.bodyIndex, data_struct.bodyColors[0], data_struct.bodyColors[1], data_struct.bodyColors[2] ); data_struct.body_render_options = render_options; } function set_head( data_struct, mode, headIndex ) { data_struct.headIndex = headIndex; data_struct.headModel = GetCharacterHeadModel( headIndex, mode ); render_options = GetCharacterHeadRenderOptions( headIndex ); data_struct.head_render_options = render_options; } function set_helmet( data_struct, mode, characterIndex, helmetIndex, helmetColors ) { data_struct.helmetIndex = helmetIndex; data_struct.helmetModel = GetCharacterHelmetModel( characterIndex, helmetIndex, mode ); set_helmet_colors( data_struct, helmetColors ); } function set_showcase_weapon( data_struct, mode, localClientNum, xuid, characterIndex, showcaseWeaponName, showcaseWeaponAttachmentInfo, weaponRenderOptions, useShowcasePaintjob, useLocalPaintshop ) { if ( isdefined( xuid ) ) { SetShowcaseWeaponPaintshopXUID( localClientNum, xuid ); } else { SetShowcaseWeaponPaintshopXUID( localClientNum ); } data_struct.showcaseWeaponName = showcaseWeaponName; data_struct.showcaseWeaponModel = GetWeaponWithAttachments( showcaseWeaponName ); if ( data_struct.showcaseWeaponModel == GetWeapon( "none" ) ) { // Fallback in case there is no weapon. data_struct.showcaseWeaponModel = GetWeapon( "ar_standard" ); data_struct.showcaseWeaponName = data_struct.showcaseWeaponModel.name; } attachmentNames = []; attachmentIndices = []; tokenizedAttachmentInfo = strtok( showcaseWeaponAttachmentInfo, "," ); for ( index = 0; index + 1 < tokenizedAttachmentInfo.size; index += 2 ) { attachmentNames[ attachmentNames.size ] = tokenizedAttachmentInfo[ index ]; attachmentIndices[ attachmentIndices.size ] = int( tokenizedAttachmentInfo[ index + 1 ] ); } for ( index = tokenizedAttachmentInfo.size; index + 1 < 16; index += 2 ) { attachmentNames[ attachmentNames.size ] = "none"; attachmentIndices[ attachmentIndices.size ] = 0; } data_struct.acvi = GetAttachmentCosmeticVariantIndexes( data_struct.showcaseWeaponModel, attachmentNames[ 0 ], attachmentIndices[ 0 ], attachmentNames[ 1 ], attachmentIndices[ 1 ], attachmentNames[ 2 ], attachmentIndices[ 2 ], attachmentNames[ 3 ], attachmentIndices[ 3 ], attachmentNames[ 4 ], attachmentIndices[ 4 ], attachmentNames[ 5 ], attachmentIndices[ 5 ], attachmentNames[ 6 ], attachmentIndices[ 6 ], attachmentNames[ 7 ], attachmentIndices[ 7 ] ); camoIndex = 0; paintjobSlot = 15; paintjobIndex = 15; showPaintshop = false; tokenizedWeaponRenderOptions = strtok( weaponRenderOptions, "," ); if ( tokenizedWeaponRenderOptions.size > 2 ) { camoIndex = int( tokenizedWeaponRenderOptions[ 0 ] ); paintjobSlot = int( tokenizedWeaponRenderOptions[ 1 ] ); paintjobIndex = int( tokenizedWeaponRenderOptions[ 2 ] ); showPaintshop = paintjobSlot != 15 && paintjobIndex != 15; } paintshopClassType = 0; if ( useShowcasePaintjob ) { paintshopClassType = 1; } else if ( useLocalPaintshop ) { paintshopClassType = 2; } data_struct.weaponRenderOptions = CalcWeaponOptions( localClientNum, camoIndex, 0, 0, false, false, showPaintshop, paintshopClassType ); weapon_root_name = data_struct.showcaseWeaponModel.rootWeapon.name; weapon_is_dual_wield = data_struct.showcaseWeaponModel.isdualwield; weapon_group = GetItemGroupForWeaponName( weapon_root_name ); if ( weapon_group == "weapon_launcher" ) { if ( weapon_root_name == "launcher_lockonly" || weapon_root_name == "launcher_multi" ) { weapon_group = "weapon_launcher_alt"; } else if ( weapon_root_name == "launcher_ex41" ) { weapon_group = "weapon_smg_ppsh"; } } else if( weapon_group == "weapon_assault") { if (weapon_root_name == "ar_m14") { weapon_group = "weapon_shotgun_olympia"; } } else if ( weapon_group == "weapon_pistol" && weapon_is_dual_wield ) { weapon_group = "weapon_pistol_dw"; } else if ( weapon_group == "weapon_smg") { if ( weapon_root_name == "smg_ppsh" ) { weapon_group = "weapon_smg_ppsh"; } else if ( weapon_root_name == "smg_sten2" ) { weapon_group = "weapon_knuckles"; } } else if ( weapon_group == "weapon_cqb") { if ( weapon_root_name == "shotgun_olympia" ) { weapon_group = "weapon_shotgun_olympia"; } } else if ( weapon_group == "weapon_special" ) { if ( weapon_root_name == "special_crossbow" || weapon_root_name == "special_discgun" ) { weapon_group = "weapon_smg"; } else if( weapon_root_name == "special_crossbow_dw" ) { weapon_group = "weapon_pistol_dw"; } else if( weapon_root_name == "knife_ballistic" ) { weapon_group = "weapon_knife_ballistic"; } } else if ( weapon_group == "weapon_knife" ) { if ( weapon_root_name == "melee_knuckles" || weapon_root_name == "melee_boxing" ) { weapon_group = "weapon_knuckles"; } else if ( weapon_root_name == "melee_chainsaw" || weapon_root_name == "melee_boneglass" || weapon_root_name == "melee_crescent" ) { weapon_group = "weapon_chainsaw"; } else if ( weapon_root_name == "melee_improvise" || weapon_root_name == "melee_shovel" ) { weapon_group = "weapon_improvise"; } else if ( weapon_root_name == "melee_wrench" || weapon_root_name == "melee_crowbar" || weapon_root_name == "melee_shockbaton" ) { weapon_group = "weapon_wrench"; } else if ( weapon_root_name == "melee_nunchuks" ) { weapon_group = "weapon_nunchucks"; } else if ( weapon_root_name == "melee_sword" || weapon_root_name == "melee_bat" || weapon_root_name == "melee_fireaxe" || weapon_root_name == "melee_mace" || weapon_root_name == "melee_katana" ) { weapon_group = "weapon_sword"; } else if ( weapon_root_name == "melee_prosthetic" ) { weapon_group = "weapon_prosthetic"; } } else if ( weapon_group == "miscweapon" ) { if ( weapon_root_name == "blackjack_coin" ) { weapon_group = "brawler"; } else if ( weapon_root_name == "blackjack_cards" ) { weapon_group = "brawler"; } } if ( data_struct.characterMode === 0 ) { data_struct.anim_name = "pb_cac_rifle_showcase_cp"; } else if ( isdefined( associativeArray( "weapon_smg", "pb_cac_smg_showcase", "weapon_assault", "pb_cac_rifle_showcase", "weapon_cqb", "pb_cac_rifle_showcase", "weapon_lmg", "pb_cac_rifle_showcase", "weapon_sniper", "pb_cac_sniper_showcase", "weapon_pistol", "pb_cac_pistol_showcase", "weapon_pistol_dw", "pb_cac_pistol_dw_showcase", "weapon_launcher", "pb_cac_launcher_showcase", "weapon_launcher_alt", "pb_cac_launcher_alt_showcase", "weapon_knife", "pb_cac_knife_showcase", "weapon_knuckles", "pb_cac_brass_knuckles_showcase", "weapon_wrench", "pb_cac_wrench_showcase", "weapon_improvise", "pb_cac_improvise_showcase", "weapon_sword", "pb_cac_sword_showcase", "weapon_nunchucks", "pb_cac_nunchucks_showcase", "weapon_mace", "pb_cac_sword_showcase", "brawler", "pb_cac_brawler_showcase", "weapon_prosthetic", "pb_cac_prosthetic_arm_showcase", "weapon_chainsaw", "pb_cac_chainsaw_showcase", "weapon_smg_ppsh", "pb_cac_smg_ppsh_showcase", "weapon_knife_ballistic", "pb_cac_b_knife_showcase", "weapon_shotgun_olympia", "pb_cac_shotgun_olympia_showcase" )[ weapon_group ] ) ) { data_struct.anim_name = associativeArray( "weapon_smg", "pb_cac_smg_showcase", "weapon_assault", "pb_cac_rifle_showcase", "weapon_cqb", "pb_cac_rifle_showcase", "weapon_lmg", "pb_cac_rifle_showcase", "weapon_sniper", "pb_cac_sniper_showcase", "weapon_pistol", "pb_cac_pistol_showcase", "weapon_pistol_dw", "pb_cac_pistol_dw_showcase", "weapon_launcher", "pb_cac_launcher_showcase", "weapon_launcher_alt", "pb_cac_launcher_alt_showcase", "weapon_knife", "pb_cac_knife_showcase", "weapon_knuckles", "pb_cac_brass_knuckles_showcase", "weapon_wrench", "pb_cac_wrench_showcase", "weapon_improvise", "pb_cac_improvise_showcase", "weapon_sword", "pb_cac_sword_showcase", "weapon_nunchucks", "pb_cac_nunchucks_showcase", "weapon_mace", "pb_cac_sword_showcase", "brawler", "pb_cac_brawler_showcase", "weapon_prosthetic", "pb_cac_prosthetic_arm_showcase", "weapon_chainsaw", "pb_cac_chainsaw_showcase", "weapon_smg_ppsh", "pb_cac_smg_ppsh_showcase", "weapon_knife_ballistic", "pb_cac_b_knife_showcase", "weapon_shotgun_olympia", "pb_cac_shotgun_olympia_showcase" )[ weapon_group ]; } } function set_helmet_colors( data_struct, colors ) { for ( i = 0; i < colors.size && i < data_struct.helmetColors.size; i++ ) { set_helmet_color( data_struct, i, colors[ i ] ); } render_options = GetCharacterHelmetRenderOptions( data_struct.characterIndex, data_struct.helmetIndex, data_struct.helmetColors[0], data_struct.helmetColors[1], data_struct.helmetColors[2] ); data_struct.helmet_render_options = render_options; } function set_helmet_color( data_struct, colorSlot, colorIndex ) { data_struct.helmetColors[ colorSlot ] = colorIndex; render_options = GetCharacterHelmetRenderOptions( data_struct.characterIndex, data_struct.helmetIndex, data_struct.helmetColors[0], data_struct.helmetColors[1], data_struct.helmetColors[2] ); data_struct.helmet_render_options = render_options; } function update( localClientNum, data_struct, params ) { data_struct.characterModel SetBodyRenderOptions( data_struct.mode_render_options, data_struct.body_render_options, data_struct.helmet_render_options, data_struct.head_render_options ); helmet_model = "tag_origin"; show_helmet = data_struct.show_helmets && ( !isdefined( params ) || !( isdefined( params.hide_helmet ) && params.hide_helmet ) ); if ( show_helmet ) { helmet_model = data_struct.helmetModel; } update_model_attachment( localClientNum, data_struct, helmet_model, "helmet", undefined, undefined, true ); head_model = data_struct.headModel; if ( show_helmet && isdefined( params ) && GetCharacterHelmetHidesHead( data_struct.characterIndex, data_struct.helmetIndex, (isdefined(params.sessionMode)?params.sessionMode:data_struct.characterMode) ) ) { assert( helmet_model != "tag_origin" ); head_model = "tag_origin"; } update_model_attachment( localClientNum, data_struct, head_model, "head", undefined, undefined, true ); changed = update_character_animation_and_attachments( localClientNum, data_struct, params ); // Used by epic taunts to clone the model and match skins data_struct.characterModel.bodyModel = data_struct.bodyModel; data_struct.characterModel.helmetModel = data_struct.helmetModel; data_struct.characterModel.modeRenderOptions = data_struct.mode_render_options; data_struct.characterModel.bodyRenderOptions = data_struct.body_render_options; data_struct.characterModel.helmetRenderOptions = data_struct.helmet_render_options; data_struct.characterModel.headRenderOptions = data_struct.head_render_options; return changed; } function is_character_streamed( data_struct ) { if( isDefined( data_struct.characterModel ) ) { if( !( data_struct.characterModel isStreamed() ) ) { return false; } } foreach( ent in data_struct.attached_entities ) { if( isDefined( ent ) ) { if( !( ent isStreamed() ) ) { return false; } } } return true; } function setup_character_streaming( data_struct ) { // init, force high detail if( isDefined( data_struct.characterModel ) ) { data_struct.characterModel SetHighDetail( true, data_struct.alt_render_mode ); } foreach( ent in data_struct.attached_entities ) { if( isDefined( ent ) ) { ent SetHighDetail( true, data_struct.alt_render_mode ); } } } function get_character_mode( localClientNum ) { return GetEquippedHeroMode( localClientNum ); } function get_character_body( localClientNum, characterMode, characterIndex, extracamData ) { assert( isdefined( characterIndex ) ); if ( characterMode === 2 && SessionModeIsCampaignGame() && GetDvarString( "mapname" ) == "core_frontend" ) { mapIndex = GetDStat( localClientNum, "highestMapReached" ); if ( isDefined( mapindex ) && mapIndex < 1) //robot after ethiopia mission { str_gender = GetHeroGender( GetEquippedHeroIndex( localClientNum, 2 ), "cp" ); n_body_id = GetCharacterBodyStyleIndex( str_gender=="female", "CPUI_OUTFIT_PROLOGUE" ); return n_body_id;//always the flesh body in the frontend for cp - user edits body in safehouse } } if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return 0; } else if( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedBodyIndexForHero( localClientNum, characterMode, extracamData.jobIndex, true ); } else if ( isdefined( extracamData ) && isdefined( extracamData.useBodyIndex ) ) { return extracamData.useBodyIndex; } else if ( isdefined( extracamData ) && ( isdefined( extracamData.defaultImageRender ) && extracamData.defaultImageRender ) ) { return 0; } else { return GetEquippedBodyIndexForHero( localClientNum, characterMode, characterIndex ); } } function get_character_body_color( localClientNum, characterMode, characterIndex, bodyIndex, colorSlot, extracamData ) { if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return 0; } else if( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedBodyAccentColorForHero( localClientNum, characterMode, extracamData.jobIndex, bodyIndex, colorSlot, true ); } else if ( isdefined( extracamData ) && ( isdefined( extracamData.defaultImageRender ) && extracamData.defaultImageRender ) ) { return 0; } else { return GetEquippedBodyAccentColorForHero( localClientNum, characterMode, characterIndex, bodyIndex, colorSlot ); } } function get_character_body_colors( localClientNum, characterMode, characterIndex, bodyIndex, extracamData ) { bodyAccentColorCount = GetBodyAccentColorCountForHero( localClientNum, characterMode, characterIndex, bodyIndex ); colors = []; for( i = 0; i < 3; i++ ) { colors[ i ] = 0; } for( i = 0; i < bodyAccentColorCount; i++ ) { colors[ i ] = get_character_body_color( localClientNum, characterMode, characterIndex, bodyIndex, i, extracamData ); } return colors; } function get_character_head( localClientNum, characterMode, extracamData ) { if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return 0; } else if ( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedHeadIndexForHero( localClientNum, characterMode, extracamData.jobIndex ); } else if ( isdefined( extracamData ) && isdefined( extracamData.useHeadIndex ) ) { return extracamData.useHeadIndex; } else if ( isdefined( extracamData ) && ( isdefined( extracamData.defaultImageRender ) && extracamData.defaultImageRender ) ) { return 0; } else { return GetEquippedHeadIndexForHero( localClientNum, characterMode ); } } function get_character_helmet( localClientNum, characterMode, characterIndex, extracamData ) { if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return 0; } else if ( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedHelmetIndexForHero( localClientNum, characterMode, extracamData.jobIndex, true ); } else if ( isdefined( extracamData ) && isdefined( extracamData.useHelmetIndex ) ) { return extracamData.useHelmetIndex; } else if ( isdefined( extracamData ) && ( isdefined( extracamData.defaultImageRender ) && extracamData.defaultImageRender ) ) { return 0; } else { return GetEquippedHelmetIndexForHero( localClientNum, characterMode, characterIndex ); } } function get_character_showcase_weapon( localClientNum, characterMode, characterIndex, extracamData ) { if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return undefined; } else if ( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedShowcaseWeaponForHero( localClientNum, characterMode, extracamData.jobIndex, true ); } else if ( isdefined( extracamData ) && isdefined( extracamData.useShowcaseWeapon ) ) { return extracamData.useShowcaseWeapon; } else { return GetEquippedShowcaseWeaponForHero( localClientNum, characterMode, characterIndex ); } } function get_character_helmet_color( localClientNum, characterMode, characterIndex, helmetIndex, colorSlot, extracamData ) { if( isdefined( extracamData ) && ( isdefined( extracamData.isDefaultHero ) && extracamData.isDefaultHero ) ) { return 0; } else if ( isdefined( extracamData ) && extracamData.useLobbyPlayers ) { return GetEquippedHelmetAccentColorForHero( localClientNum, characterMode, extracamData.jobIndex, helmetIndex, colorSlot, true ); } else if ( isdefined( extracamData ) && ( isdefined( extracamData.defaultImageRender ) && extracamData.defaultImageRender ) ) { return 0; } else { return GetEquippedHelmetAccentColorForHero( localClientNum, characterMode, characterIndex, helmetIndex, colorSlot ); } } function get_character_helmet_colors( localClientNum, characterMode, characterIndex, helmetIndex, extracamData ) { helmetColorCount = GetHelmetAccentColorCountForHero( localClientNum, characterMode, characterIndex, helmetIndex ); colors = []; for( i = 0; i < 3; i++ ) { colors[ i ] = 0; } for( i = 0; i < helmetColorCount; i++ ) { colors[ i ] = get_character_helmet_color( localClientNum, characterMode, characterIndex, helmetIndex, i, extracamData ); } return colors; } #using_animtree("all_player"); function update_character_animation_tree_for_scene(characterModel) { if ( !characterModel HasAnimTree() ) { characterModel UseAnimTree( #animtree ); } } function reaper_body3_hack( params ) { if ( IsDefined(params.weapon_right) && params.weapon_right == "wpn_t7_hero_reaper_minigun_prop" && isDefined( level.mp_lobby_data_struct.characterModel ) && IsSubStr(level.mp_lobby_data_struct.characterModel.model, "body3") ) { params.weapon_right = "wpn_t7_loot_hero_reaper3_minigun_prop"; params.weapon = GetWeapon("hero_minigun_body3"); return true; } return false; } function get_current_frozen_moment_params( localClientNum, data_struct, params ) { fields = GetCharacterFields( data_struct.characterIndex, data_struct.characterMode ); if ( data_struct.frozenMomentStyle == "weapon" ) { if ( isdefined( fields.weaponFrontendFrozenMomentXAnim) ) { params.anim_name = fields.weaponFrontendFrozenMomentXAnim; }; params.scene = undefined; if ( isdefined( fields.weaponFrontendFrozenMomentWeaponLeftModel) ) { params.weapon_left = fields.weaponFrontendFrozenMomentWeaponLeftModel; }; if ( isdefined( fields.weaponFrontendFrozenMomentWeaponLeftAnim) ) { params.weapon_left_anim = fields.weaponFrontendFrozenMomentWeaponLeftAnim; }; if ( isdefined( fields.weaponFrontendFrozenMomentWeaponRightModel) ) { params.weapon_right = fields.weaponFrontendFrozenMomentWeaponRightModel; }; if ( isdefined( fields.weaponFrontendFrozenMomentWeaponRightAnim) ) { params.weapon_right_anim = fields.weaponFrontendFrozenMomentWeaponRightAnim; }; if ( isdefined( fields.weaponFrontendFrozenMomentExploder) ) { params.exploder_id = fields.weaponFrontendFrozenMomentExploder; }; if ( isdefined( struct::get( fields.weaponFrontendFrozenMomentAlignTarget )) ) { params.align_struct = struct::get( fields.weaponFrontendFrozenMomentAlignTarget ); }; if ( isdefined( fields.weaponFrontendFrozenMomentXCam) ) { params.xcam = fields.weaponFrontendFrozenMomentXCam; }; if ( isdefined( fields.weaponFrontendFrozenMomentXCamSubXCam) ) { params.subXCam = fields.weaponFrontendFrozenMomentXCamSubXCam; }; if ( isdefined( fields.weaponFrontendFrozenMomentXCamFrame) ) { params.xcamFrame = fields.weaponFrontendFrozenMomentXCamFrame; }; } else if ( data_struct.frozenMomentStyle == "ability" ) { if ( isdefined( fields.abilityFrontendFrozenMomentXAnim) ) { params.anim_name = fields.abilityFrontendFrozenMomentXAnim; }; params.scene = undefined; if ( isdefined( fields.abilityFrontendFrozenMomentWeaponLeftModel) ) { params.weapon_left = fields.abilityFrontendFrozenMomentWeaponLeftModel; }; if ( isdefined( fields.abilityFrontendFrozenMomentWeaponLeftAnim) ) { params.weapon_left_anim = fields.abilityFrontendFrozenMomentWeaponLeftAnim; }; if ( isdefined( fields.abilityFrontendFrozenMomentWeaponRightModel) ) { params.weapon_right = fields.abilityFrontendFrozenMomentWeaponRightModel; }; if ( isdefined( fields.abilityFrontendFrozenMomentWeaponRightAnim) ) { params.weapon_right_anim = fields.abilityFrontendFrozenMomentWeaponRightAnim; }; if ( isdefined( fields.abilityFrontendFrozenMomentExploder) ) { params.exploder_id = fields.abilityFrontendFrozenMomentExploder; }; if ( isdefined( struct::get( fields.abilityFrontendFrozenMomentAlignTarget )) ) { params.align_struct = struct::get( fields.abilityFrontendFrozenMomentAlignTarget ); }; if ( isdefined( fields.abilityFrontendFrozenMomentXCam) ) { params.xcam = fields.abilityFrontendFrozenMomentXCam; }; if ( isdefined( fields.abilityFrontendFrozenMomentXCamSubXCam) ) { params.subXCam = fields.abilityFrontendFrozenMomentXCamSubXCam; }; if ( isdefined( fields.abilityFrontendFrozenMomentXCamFrame) ) { params.xcamFrame = fields.abilityFrontendFrozenMomentXCamFrame; }; } reaper_body3_hack( params ); if ( !isdefined( params.align_struct ) ) { params.align_struct = data_struct; // moves the character back to their original position } } function play_intro_and_animation( intro_anim_name, anim_name, b_keep_link ) { self notify( "stop_vignette_animation" ); self endon( "stop_vignette_animation" ); if ( isdefined(intro_anim_name) ) { self animation::play( intro_anim_name, self.chosenOrigin, self.chosenAngles, 1, 0, 0, 0, b_keep_link ); } self animation::play( anim_name, self.chosenOrigin, self.chosenAngles, 1, 0, 0, 0, b_keep_link ); } function update_character_animation_based_on_showcase_weapon( data_struct, params ) { if ( !isdefined( params.weapon_right ) && !isdefined( params.weapon_left ) ) { if ( isdefined( data_struct.anim_name ) ) { params.anim_name = data_struct.anim_name; } } } function update_character_animation_and_attachments( localClientNum, data_struct, params ) { changed = false; if ( !isdefined( params ) ) { params = SpawnStruct(); } if ( data_struct.useFrozenMomentAnim && isdefined( data_struct.frozenMomentStyle ) ) { get_current_frozen_moment_params( localClientNum, data_struct, params ); } if ( !isdefined( params.exploder_id ) ) { params.exploder_id = data_struct.default_exploder; } align_changed = false; if(!isdefined(params.align_struct))params.align_struct=struct::get( data_struct.align_target ); if(!isdefined(params.align_struct))params.align_struct=data_struct; if ( isdefined( params.align_struct ) && ( params.align_struct.origin !== data_struct.characterModel.chosenOrigin || params.align_struct.angles !== data_struct.characterModel.chosenAngles ) ) { data_struct.characterModel.chosenOrigin = params.align_struct.origin; data_struct.characterModel.chosenAngles = params.align_struct.angles; params.anim_name = ( isdefined( params.anim_name ) ? params.anim_name : data_struct.currentAnimation ); align_changed = true; } if ( ( isdefined( data_struct.allow_showcase_weapons ) && data_struct.allow_showcase_weapons ) ) { update_character_animation_based_on_showcase_weapon( data_struct, params ); } if ( character_customization::reaper_body3_hack( params ) ) { align_changed = true; changed = true; } if ( IsDefined( params.weapon_right ) && params.weapon_right !== data_struct.weapon_right ) { align_changed = true; } if ( isdefined( params.anim_name ) && ( params.anim_name !== data_struct.currentAnimation || align_changed ) ) { changed = true; end_game_taunts::cancelTaunt( localClientNum, data_struct.characterModel ); end_game_taunts::cancelGesture( data_struct.characterModel ); data_struct.currentAnimation = params.anim_name; data_struct.weapon_right = params.weapon_right; if ( !data_struct.characterModel HasAnimTree() ) { data_struct.characterModel UseAnimTree( #animtree ); } data_struct.characterModel thread play_intro_and_animation( params.anim_intro_name, params.anim_name, false ); } else if ( isdefined( params.scene ) && params.scene !== data_struct.currentScene ) { if ( isdefined( data_struct.currentScene ) ) { level scene::stop( data_struct.currentScene, false ); } update_character_animation_tree_for_scene(data_struct.characterModel); data_struct.currentScene = params.scene; level thread scene::play( params.scene ); } if ( data_struct.exploder_id !== params.exploder_id ) { if ( isdefined( data_struct.exploder_id ) ) { KillRadiantExploder( localClientNum, data_struct.exploder_id ); } if ( isdefined( params.exploder_id ) ) { PlayRadiantExploder( localClientNum, params.exploder_id ); } data_struct.exploder_id = params.exploder_id; } if ( isdefined( params.weapon_right ) || isdefined( params.weapon_left ) ) { update_model_attachment( localClientNum, data_struct, params.weapon_right, "tag_weapon_right", params.weapon_right_anim, params.weapon_right_anim_intro, align_changed ); update_model_attachment( localClientNum, data_struct, params.weapon_left, "tag_weapon_left", params.weapon_left_anim, params.weapon_left_anim_intro, align_changed ); } else if ( isdefined( data_struct.showcaseWeaponModel ) ) { if( isdefined( data_struct.attached_models["tag_weapon_right"] ) && data_struct.characterModel IsAttached( data_struct.attached_models["tag_weapon_right"], "tag_weapon_right" ) ) { data_struct.characterModel Detach( data_struct.attached_models["tag_weapon_right"], "tag_weapon_right" ); } if( isdefined( data_struct.attached_models["tag_weapon_left"] ) && data_struct.characterModel IsAttached( data_struct.attached_models["tag_weapon_left"], "tag_weapon_left" ) ) { data_struct.characterModel Detach( data_struct.attached_models["tag_weapon_left"], "tag_weapon_left" ); } data_struct.characterModel AttachWeapon( data_struct.showcaseWeaponModel, data_struct.weaponRenderOptions, data_struct.acvi ); data_struct.characterModel UseWeaponHideTags( data_struct.showcaseWeaponModel ); data_struct.characterModel.showcaseWeapon = data_struct.showcaseWeaponModel; data_struct.characterModel.showcaseWeaponRenderOptions = data_struct.weaponRenderOptions; data_struct.characterModel.showcaseWeaponACVI = data_struct.acvi; } return changed; } function update_use_frozen_moments( localClientNum, data_struct, useFrozenMoments ) { if ( data_struct.useFrozenMomentAnim != useFrozenMoments ) { data_struct.useFrozenMomentAnim = useFrozenMoments; params = SpawnStruct(); if ( !data_struct.useFrozenMomentAnim ) { params.align_struct = struct::get( "character_customization" ); params.anim_name = "pb_cac_main_lobby_idle"; } MarkAsDirty( data_struct.characterModel ); update_character_animation_and_attachments( localClientNum, data_struct, params ); if ( data_struct.useFrozenMomentAnim ) { level notify( "frozenMomentChanged" + localClientNum ); } } } function update_show_helmets( localClientNum, data_struct, show_helmets ) { if ( data_struct.show_helmets != show_helmets ) { data_struct.show_helmets = show_helmets; params = SpawnStruct(); params.weapon_right = data_struct.attached_models["tag_weapon_right"]; params.weapon_left = data_struct.attached_models["tag_weapon_left"]; update( localClientNum, data_struct, params ); } } function set_character_align( localClientNum, data_struct, align_target ) { if ( data_struct.align_target !== align_target ) { data_struct.align_target = align_target; params = SpawnStruct(); params.weapon_right = data_struct.attached_models["tag_weapon_right"]; params.weapon_left = data_struct.attached_models["tag_weapon_left"]; update( localClientNum, data_struct, params ); } } /////////////////////////////////////////////////////////////////////////// // LIVE CHARACTER /////////////////////////////////////////////////////////////////////////// function setup_live_character_customization_target( localClientNum ) { characterEnt = GetEnt( localClientNum, "character_customization", "targetname" ); if ( isdefined( characterEnt ) ) { customization_data_struct = character_customization::create_character_data_struct( characterEnt, localClientNum, true ); customization_data_struct.default_exploder = "char_customization"; customization_data_struct.allow_showcase_weapons = true; level thread updateEventThread( localClientNum, customization_data_struct ); return customization_data_struct; } return undefined; } function update_locked_shader( localClientNum, params ) { if( IsDefined( params.isItemUnlocked ) && params.isItemUnlocked != 1 ) { EnableFrontendLockedWeaponOverlay( localClientNum, true ); } else { EnableFrontendLockedWeaponOverlay( localClientNum, false ); } } function updateEventThread( localClientNum, data_struct ) { while( 1 ) { level waittill( "updateHero" + localClientNum, eventType, param1, param2, param3, param4 ); switch( eventType ) { case "update_lcn": data_struct.splitScreenClient = param1; break; case "refresh": data_struct.splitScreenClient = param1; params = spawnstruct(); params.anim_name = "pb_cac_main_lobby_idle"; params.sessionMode = param2; character_customization::loadEquippedCharacterOnModel( localClientNum, data_struct, undefined, params ); if (isdefined(param3) && param3 != "") { level.mp_lobby_data_struct.playSound = param3; } break; case "changeHero": // param1 = hero index // param2 = session mode params = spawnstruct(); params.anim_name = "pb_cac_main_lobby_idle"; params.sessionMode = param2; character_customization::loadEquippedCharacterOnModel( localClientNum, data_struct, param1, params ); break; case "changeBody": //param1 = new body index //param2 = session mode //param3 = is item unlocked params = spawnstruct(); params.sessionMode = param2; params.isItemUnlocked = param3; character_customization::set_body( data_struct, param2, data_struct.characterIndex, param1, get_character_body_colors( localClientNum, param2, data_struct.characterIndex, param1 ) ); character_customization::update( localClientNum, data_struct, params ); //update the locked shader update_locked_shader( localClientNum, params ); break; case "changeHelmet": //param1 = new helmet index //param2 = session mode //param3 = is item unlocked params = spawnstruct(); params.sessionMode = param2; params.isItemUnlocked = param3; character_customization::set_helmet( data_struct, param2, data_struct.characterIndex, param1, get_character_helmet_colors( localClientNum, param2, data_struct.characterIndex, param1 ) ); character_customization::update( localClientNum, data_struct, params ); //update the locked shader update_locked_shader( localClientNum, params ); break; case "changeShowcaseWeapon": //param1 = showcase weapon name //param2 = attachment info //param3 = camo and paintjob info //param4 = session mode params = spawnstruct(); params.sessionMode = param4; character_customization::set_showcase_weapon( data_struct, param4, localClientNum, undefined, data_struct.characterIndex, param1, param2, param3, false, true ); character_customization::update( localClientNum, data_struct, params ); break; case "changeHead": //param1 = head index params = spawnstruct(); params.sessionMode = param2; character_customization::set_head( data_struct, param2, param1 ); character_customization::update( localClientNum, data_struct, params ); break; case "changeBodyAccentColor": //param1 = accent color slot //param2 = accent color index params = spawnstruct(); params.sessionMode = param3; character_customization::set_body_color( data_struct, param1, param2 ); character_customization::update( localClientNum, data_struct, params ); break; case "changeHelmetAccentColor": //param1 = accent color slot //param2 = accent color index //param3 = sessionMode params = spawnstruct(); params.sessionMode = param3; character_customization::set_helmet_color( data_struct, param1, param2 ); character_customization::update( localClientNum, data_struct, params ); break; case "changeFrozenMoment": //param1 = new frozen moment type data_struct.frozenMomentStyle = param1; if ( data_struct.useFrozenMomentAnim ) { MarkAsDirty( data_struct.characterModel ); update_character_animation_and_attachments( localClientNum, data_struct, undefined ); } level notify( "frozenMomentChanged" + localClientNum ); break; case "previewGesture": //param1 = new anim name data_struct.currentAnimation = param1; thread end_game_taunts::previewGesture( localClientNum, data_struct.characterModel, data_struct.anim_name, param1 ); break; case "previewTaunt": //param1 = new anim name if ( character_customization::is_character_streamed( data_struct ) ) { data_struct.currentAnimation = param1; thread end_game_taunts::previewTaunt( localClientNum, data_struct.characterModel, data_struct.anim_name, param1 ); } break; } } } function rotation_thread_spawner( localClientNum, data_struct, endOnEvent ) { if ( !isdefined( endOnEvent ) ) { return; } assert( isdefined( data_struct.characterModel ) ); model = data_struct.characterModel; baseAngles = model.angles; level thread update_model_rotation_for_right_stick( localClientNum, data_struct, endOnEvent ); level waittill( endOnEvent ); if ( !( isdefined( data_struct.characterModel.anglesOverride ) && data_struct.characterModel.anglesOverride ) ) { model.angles = baseAngles; } } function update_model_rotation_for_right_stick( localClientNum, data_struct, endOnEvent ) { level endon( endOnEvent ); assert( isdefined( data_struct.characterModel ) ); model = data_struct.characterModel; while ( true ) { data_lcn = (isdefined(data_struct.splitScreenClient)?data_struct.splitScreenClient:localClientNum); if ( LocalClientActive( data_lcn ) && !( isdefined( data_struct.characterModel.anglesOverride ) && data_struct.characterModel.anglesOverride ) ) { pos = GetControllerPosition( data_lcn ); if ( isdefined( pos["rightStick"] ) ) { model.angles = ( model.angles[0], AbsAngleClamp360( model.angles[1] + pos["rightStick"][0] * 3.0 ), model.angles[2] ); } else { model.angles = ( model.angles[0], AbsAngleClamp360( model.angles[1] + pos["look"][0] * 3.0 ), model.angles[2] ); } if ( IsPC() ) { pos = GetXCamMouseControl( data_lcn ); model.angles = ( model.angles[0], AbsAngleClamp360( model.angles[1] - pos["yaw"] * 3.0 ), model.angles[2] ); } } {wait(.016);}; } } /////////////////////////////////////////////////////////////////////////// // STATIC CHARACTER /////////////////////////////////////////////////////////////////////////// function setup_static_character_customization_target( localClientNum ) { characterEnt = GetEnt( localClientNum, "character_customization_staging", "targetname" ); level.extra_cam_hero_data[localClientNum] = setup_character_extracam_struct( "ui_cam_character_customization", "cam_menu_unfocus", "pb_cac_main_lobby_idle", false ); level.extra_cam_lobby_client_hero_data[localClientNum] = setup_character_extracam_struct( "ui_cam_char_identity", "cam_bust", "pb_cac_vs_screen_idle_1", true ); level.extra_cam_headshot_hero_data[localClientNum] = setup_character_extracam_struct( "ui_cam_char_identity", "cam_bust", "pb_cac_vs_screen_idle_1", false ); level.extra_cam_outfit_preview_data[localClientNum] = setup_character_extracam_struct( "ui_cam_char_identity", "cam_bust", "pb_cac_main_lobby_idle", false ); if ( isdefined( characterEnt ) ) { customization_data_struct = character_customization::create_character_data_struct( characterEnt, localClientNum, false ); level thread update_character_extracam( localClientNum, customization_data_struct ); return customization_data_struct; } return undefined; } function setup_character_extracam_struct( xcam, subXCam, model_animation, useLobbyPlayers ) { newStruct = SpawnStruct(); newStruct.xcam = xcam; newStruct.subXCam = subXCam; newStruct.anim_name = model_animation; newStruct.useLobbyPlayers = useLobbyPlayers; return newStruct; } function wait_for_extracam_close( localClientNum, camera_ent, extraCamIndex ) { level waittill( "render_complete_" + localClientNum + "_" + extraCamIndex ); multi_extracam::extracam_reset_index( localClientNum, extraCamIndex ); } function setup_character_extracam_settings( localClientNum, data_struct, extracam_data_struct ) { assert( isdefined( extracam_data_struct.jobIndex ) ); if(!isdefined(level.camera_ents))level.camera_ents=[]; initializedExtracam = false; camera_ent = (isDefined(level.camera_ents[localClientNum]) ? level.camera_ents[localClientNum][extracam_data_struct.extraCamIndex] : undefined); if( !isdefined( camera_ent ) ) { initializedExtracam = true; multi_extracam::extracam_init_index( localClientNum, "character_staging_extracam" + (extracam_data_struct.extraCamIndex+1), extracam_data_struct.extraCamIndex); camera_ent = level.camera_ents[localClientNum][extracam_data_struct.extraCamIndex]; } assert( isdefined( camera_ent ) ); camera_ent PlayExtraCamXCam( extracam_data_struct.xcam, 0, extracam_data_struct.subXCam ); params = spawnstruct(); params.anim_name = extracam_data_struct.anim_name; params.extracam_data = extracam_data_struct; params.isDefaultHero = extracam_data_struct.isDefaultHero; params.sessionMode = extracam_data_struct.sessionMode; params.hide_helmet = ( isdefined( extracam_data_struct.hideHelmet ) && extracam_data_struct.hideHelmet ); data_struct.alt_render_mode = false; loadEquippedCharacterOnModel( localClientNum, data_struct, extracam_data_struct.characterIndex, params ); while( !is_character_streamed( data_struct ) ) { {wait(.016);}; } if ( ( isdefined( extracam_data_struct.defaultImageRender ) && extracam_data_struct.defaultImageRender ) ) { wait 0.5; // we can afford longer waits for the default images just make sure they look pretty } else { wait 0.1; // wait for a bit to allow the models to get set up correctly and have the lighting update } setExtraCamRenderReady( extracam_data_struct.jobIndex ); extracam_data_struct.jobIndex = undefined; if( initializedExtracam ) { level thread wait_for_extracam_close( localClientNum, camera_ent, extracam_data_struct.extraCamIndex ); } } function update_character_extracam( localClientNum, data_struct ) { level endon( "disconnect" ); while ( true ) { level waittill( "process_character_extracam" + localClientNum, extracam_data_struct ); setup_character_extracam_settings( localClientNum, data_struct, extracam_data_struct ); } } function process_character_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, characterIndex ) { level.extra_cam_hero_data[localClientNum].jobIndex = jobIndex; level.extra_cam_hero_data[localClientNum].extraCamIndex = extraCamIndex; level.extra_cam_hero_data[localClientNum].characterIndex = characterIndex; level.extra_cam_hero_data[localClientNum].sessionMode = sessionMode; level notify( "process_character_extracam" + localClientNum, level.extra_cam_hero_data[localClientNum] ); } function process_lobby_client_character_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode ) { level.extra_cam_lobby_client_hero_data[localClientNum].jobIndex = jobIndex; level.extra_cam_lobby_client_hero_data[localClientNum].extraCamIndex = extraCamIndex; level.extra_cam_lobby_client_hero_data[localClientNum].characterIndex = GetEquippedCharacterIndexForLobbyClientHero( localClientNum, jobIndex ); level.extra_cam_lobby_client_hero_data[localClientNum].sessionMode = sessionMode; level notify( "process_character_extracam" + localClientNum, level.extra_cam_lobby_client_hero_data[localClientNum] ); } function process_current_hero_headshot_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, characterIndex, isDefaultHero ) { level.extra_cam_headshot_hero_data[localClientNum].jobIndex = jobIndex; level.extra_cam_headshot_hero_data[localClientNum].extraCamIndex = extraCamIndex; level.extra_cam_headshot_hero_data[localClientNum].characterIndex = characterIndex; level.extra_cam_headshot_hero_data[localClientNum].isDefaultHero = isDefaultHero; level.extra_cam_headshot_hero_data[localClientNum].sessionMode = sessionMode; level notify( "process_character_extracam" + localClientNum, level.extra_cam_headshot_hero_data[localClientNum] ); } function process_outfit_preview_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, outfitIndex ) { level.extra_cam_outfit_preview_data[localClientNum].jobIndex = jobIndex; level.extra_cam_outfit_preview_data[localClientNum].extraCamIndex = extraCamIndex; level.extra_cam_outfit_preview_data[localClientNum].characterIndex = outfitIndex; level.extra_cam_outfit_preview_data[localClientNum].sessionMode = sessionMode; level notify( "process_character_extracam" + localClientNum, level.extra_cam_outfit_preview_data[localClientNum] ); } function process_character_body_item_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, characterIndex, itemIndex, defaultImageRender ) { extracam_data = undefined; if ( defaultImageRender ) { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons_render", "loot_body", "pb_cac_vs_screen_idle_1", false ); extracam_data.useHeadIndex = GetFirstHeadOfGender( GetHeroGender( characterIndex, sessionMode ), sessionMode ); } else { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons", "cam_body", "pb_cac_vs_screen_idle_1", false ); } extracam_data.jobIndex = jobIndex; extracam_data.extraCamIndex = extraCamIndex; extracam_data.sessionMode = sessionMode; extracam_data.characterIndex = characterIndex; extracam_data.useBodyIndex = itemIndex; extracam_data.defaultImageRender = defaultImageRender; level notify( "process_character_extracam" + localClientNum, extracam_data ); } function process_character_helmet_item_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, characterIndex, itemIndex, defaultImageRender ) { extracam_data = undefined; if ( defaultImageRender ) { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons_render", "loot_helmet", "pb_cac_vs_screen_idle_1", false ); //#if XFILE_VERSION >= 553 extracam_data.useHeadIndex = GetFirstHeadOfGender( GetHeroGender( characterIndex, sessionMode ), sessionMode ); //#endif // #if XFILE_VERSION >= 553 } else { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons", "cam_helmet", "pb_cac_vs_screen_idle_1", false ); } extracam_data.jobIndex = jobIndex; extracam_data.extraCamIndex = extraCamIndex; extracam_data.sessionMode = sessionMode; extracam_data.characterIndex = characterIndex; extracam_data.useHelmetIndex = itemIndex; extracam_data.defaultImageRender = defaultImageRender; level notify( "process_character_extracam" + localClientNum, extracam_data ); } function process_character_head_item_extracam_request( localClientNum, jobIndex, extraCamIndex, sessionMode, headIndex, defaultImageRender ) { extracam_data = undefined; if ( defaultImageRender ) { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons_render", "cam_head", "pb_cac_vs_screen_idle_1", false ); //#if XFILE_VERSION >= 553 extracam_data.characterIndex = GetFirstHeroOfGender( GetHeadGender( headIndex, sessionMode ), sessionMode ); //#endif // #if XFILE_VERSION >= 553 } else { extracam_data = setup_character_extracam_struct( "ui_cam_char_customization_icons", "cam_head", "pb_cac_vs_screen_idle_1", false ); } extracam_data.jobIndex = jobIndex; extracam_data.extraCamIndex = extraCamIndex; extracam_data.sessionMode = sessionMode; extracam_data.useHeadIndex = headIndex; extracam_data.hideHelmet = true; extracam_data.defaultImageRender = defaultImageRender; level notify( "process_character_extracam" + localClientNum, extracam_data ); }