#include maps\mp\_utility; #include common_scripts\utility; #include maps\mp\gametypes\_hud_util; /////// // movable_cover /////// init() { if( getDvar( "r_reflectionProbeGenerate" ) == "1" ) return; movable_cover_precache(); waitframe(); covers = GetEntArray("movable_cover", "targetname"); cover_proxy = getstructarray("movable_cover", "targetname"); foreach(proxy in cover_proxy) { if(IsDefined(proxy.target)) { cover = GetEnt(proxy.target, "targetname"); if(IsDefined(cover)) { covers[covers.size] = cover; } } } array_thread(covers, ::movable_cover_init); } movable_cover_precache() { level.movable_cover_use_icons = []; level.movable_cover_use_icons["dumpster"] = "hud_icon_push"; level.movable_cover_move_sounds = []; level.movable_cover_move_sounds["dumpster"]["start"] = "mp_dumpster_start"; level.movable_cover_move_sounds["dumpster"]["move"] = "mp_dumpster_mvmt_loop"; level.movable_cover_move_sounds["dumpster"]["stop"] = "mp_dumpster_end"; level.movable_cover_move_anim = []; level.movable_cover_move_anim["dumpster"] = []; level.movable_cover_move_anim["dumpster"]["move"] = "mp_lonestar_dumpster_jitter"; level.movable_cover_move_anim["dumpster"]["idle"] = "mp_lonestar_dumpster_jitter_idle"; level.movable_cover_default_parameters = []; level.movable_cover_default_parameters["dumpster"] = "goal_radius=1;max_speed=80;accel_time=.8;decel_time=.8;stances=crouch,stand"; foreach(move_anim_type in level.movable_cover_move_anim) { foreach(move_anim in move_anim_type) { PrecacheMpAnim(move_anim); } } } movable_cover_init() { self.moving = false; self.stay = false; self.updatePaths = self.spawnflags & 1; self.movable_type = "default"; if(IsDefined(self.script_noteworthy)) self.movable_type = self.script_noteworthy; self movable_cover_parse_parameters(); //Find End points end_points = []; links = self get_links(); foreach(link in links) { point = getstruct(link, "script_linkname"); if(IsDefined(point) && IsDefined(point.script_label)) { point.auto = IsDefined(point.script_parameters) && point.script_parameters=="auto"; point.stay = IsDefined(point.script_parameters) && point.script_parameters=="stay"; end_points[point.script_label] = point; } } targets = []; if(IsDefined(self.target)) { structs = GetStructArray(self.target, "targetname"); ents = GetEntArray(self.target, "targetname"); targets = array_combine(structs, ents); } link_to_ent = self; link_to_tag = undefined; if(IsDefined(level.movable_cover_move_anim[self.movable_type])) { self.animate_ent = spawn("script_model", self.origin); self.animate_ent SetModel("generic_prop_raven"); self.animate_ent.angles = self.angles; self.animate_ent linkTo(self); link_to_ent = self.animate_ent; link_to_tag = "j_prop_1"; } self.linked_ents = []; foreach(target in targets) { if(!IsDefined(target.script_noteworthy)) continue; switch(target.script_noteworthy) { case "move_trigger": if(!IsDefined(target.script_label) || !IsDefined(end_points[target.script_label])) continue; target EnableLinkTo(); target LinkTo(self); self thread movable_cover_trigger(target, end_points[target.script_label]); self thread movable_cover_update_use_icon(target, end_points[target.script_label]); break; case "link": self.linked_ents[self.linked_ents.size] = target; break; case "angels": if(IsDefined(target.angles) && IsDefined(self.animate_ent)) self.animate_ent.angles = target.angles; break; case "mantlebrush": self.linked_ents[self.linked_ents.size] = target; //self thread movable_cover_mantlebrush_think( target ); break; default: break; } } //link after to make sure the angels on animate_ent is set foreach(ent in self.linked_ents) { if(IsDefined(link_to_tag)) { ent LinkTo(link_to_ent, link_to_tag); } else { ent LinkTo(link_to_ent); } } //Traversals all_nodes = self getLinknameNodes(); self.traverse_nodes = []; foreach(node in all_nodes) { if(!IsDefined(node.type)) continue; node.node_type = node.script_noteworthy; if(!IsDefined(node.node_type)) node.node_type = "closest"; node_type_valid = false; switch(node.node_type) { case "closest": node_type_valid= true; break; case "radius": case "radius3d": //fallthrough case "radius2d": //fallthrough if(IsDefined(node.target)) { target = getstruct(node.target, "targetname"); if(IsDefined(target) && IsDefined(target.radius)) { node.test_origin = target.origin; node.test_radius = target.radius; node_type_valid= true; } } break; default: node_type_valid = false; break; } if(!node_type_valid) continue; if(node.type == "Begin" || node.type == "End") { if(node.type == "Begin") { node.connected_nodes = GetNodeArray(node.target, "targetname"); } else //"End" { node.connected_nodes = GetNodeArray(node.targetname, "target"); } //Disconnect all conenctions to start foreach(connected_node in node.connected_nodes) { DisconnectNodePair(node, connected_node); } self.traverse_nodes[self.traverse_nodes.size] = node; } } self movable_cover_connect_traversals(); //Reconnect the closest } movable_cover_set_user(user, trigger) { if(!IsDefined(self.user) && IsDefined(user)) self notify("new_user"); else if(IsDefined(self.user) && IsDefined(user) && self.user!=user) self notify("new_user"); else if(IsDefined(self.user) && !IsDefined(user)) self notify("clear_user"); self.user = user; self.user_trigger= trigger; } movable_cover_update_use_icon(trigger, move_to) { if(!IsDefined(level.movable_cover_use_icons[self.movable_type])) return; while( !IsDefined( level.players ) ) { waitframe(); continue; } show_dist=100; show_dist_sqr = show_dist*show_dist; ent_num = trigger GetEntityNumber(); trigger_name = "trigger_" + ent_num; while(1) { foreach(player in level.players) { if(!IsDefined(player.movable_cover_huds)) player.movable_cover_huds = []; dist_sqr = DistanceSquared(player.origin+(0,0,30), trigger.origin); if(dist_sqr<=show_dist_sqr && !self movable_cover_at_goal(move_to.origin)) { if(!IsDefined(player.movable_cover_huds[trigger_name])) { player.movable_cover_huds[trigger_name] = movable_cover_use_icon(player, trigger); player.movable_cover_huds[trigger_name].alpha = 0; } player.movable_cover_huds[trigger_name] notify("stop_fade"); player.movable_cover_huds[trigger_name] thread movable_cover_fade_in_use_icon(); } else { if(IsDefined(player.movable_cover_huds[trigger_name])) { player.movable_cover_huds[trigger_name] thread movable_cover_fade_out_use_icon(); } } } wait .05; } } movable_cover_fade_in_use_icon() { self endon("death"); if(self.alpha == 1) return; self FadeOverTime(.5); self.alpha = 1; } movable_cover_fade_out_use_icon() { self endon("death"); self endon("stop_fade"); if(self.alpha == 0) return; time = .5; self FadeOverTime(time); self.alpha = 0; wait time; self Destroy(); } movable_cover_use_icon(player, ent) { icon = player createIcon( level.movable_cover_use_icons[self.movable_type], 16, 16 ); icon setWayPoint( true, false ); icon SetTargetEnt(ent); icon.fading = false; return icon; } movable_cover_parse_parameters() { //Init Delfaults self.goal_radius = 1; self.max_speed = 50; self.accel_time = 1; self.decel_time = 1; self.requires_push = 1; self.start_delay = .2; self.stances = ["stand","crouch"]; if(!IsDefined(self.script_parameters)) self.script_parameters = ""; default_parameters = level.movable_cover_default_parameters[self.movable_type]; if(IsDefined(default_parameters)) self.script_parameters = default_parameters + self.script_parameters; params = StrTok(self.script_parameters, ";"); foreach(param in params) { toks = strtok(param,"="); if(toks.size!=2) continue; switch(toks[0]) { case "goal_radius": self.goal_radius = float(toks[1]); self.goal_radius = max(1,self.goal_radius); break; case "max_speed": self.max_speed = float(toks[1]); break; case "accel_time": self.accel_time = float(toks[1]); break; case "decel_time": self.decel_time = float(toks[1]); self.decel_time = max(0.05,self.decel_time); break; case "stances": self.stances = StrTok(toks[1], ","); break; case "requires_push": self.requires_push = int(toks[1]); break; case "start_delay": self.start_delay = float(toks[1]); break; default: break; } } } movable_cover_trigger(trigger, move_to) { auto = move_to.auto; stay = move_to.stay; while(1) { player=undefined; if(auto && !self.stay) { waitframe(); if(IsDefined(self.user) && self.user_trigger != trigger) continue; } else { self movable_cover_set_user(undefined, undefined); while(1) { trigger waittill("trigger", player); if(isPlayer(player)) break; } self movable_cover_set_user(player, trigger); } if(self movable_cover_at_goal(move_to.origin)) continue; move_dir = VectorNormalize(move_to.origin - self.origin); if(!auto && !self movable_cover_move_delay(self.start_delay, player, trigger, move_dir) ) continue; dist = Distance(self.origin, move_to.origin); time = dist/self.max_speed; if(auto && self.stay && !IsDefined(self.user)) continue; if(self.moving) continue; if(self.updatePaths) self ConnectPaths(); self movable_cover_disconnect_traversals(); self.moving = true; self.stay = false; self notify( "move_start" ); start_time = GetTime(); accel_time = min(time, self.accel_time); if(auto) accel_time = time; start_sound = movable_cover_get_sound("start"); if(IsDefined(start_sound)) self PlaySound(start_sound); move_sound = movable_cover_get_sound("move"); if(IsDefined(move_sound)) self PlayLoopSound(move_sound); if(IsDefined(self.animate_ent) && IsDefined(level.movable_cover_move_anim[self.movable_type]["move"])) { self.animate_ent scriptmodelPlayanim(level.movable_cover_move_anim[self.movable_type]["move"]); //self.animate_ent ScriptModelPlayAnimDeltaMotion(level.movable_cover_move_anim[self.movable_type]); } self MoveTo(move_to.origin, time, accel_time); if(auto) { self movable_cover_wait_for_user_or_timeout(time); } else { while(movable_cover_is_pushed(player, trigger, move_dir) && !self movable_cover_at_goal(move_to.origin)) { wait .05; } self movable_cover_set_user(undefined, undefined); } if(!self movable_cover_at_goal(move_to.origin)) { current_speed_scale = movable_cover_calc_move_speed_scale((GetTime()-start_time)/1000, time, accel_time); current_speed = self.max_speed * current_speed_scale; dist = Distance(self.origin, move_to.origin); stop_dist = dist; if(current_speed>0) { stop_dist = min(dist,current_speed*self.decel_time); } time = (2*stop_dist)/self.max_speed; self MoveTo(self.origin+(stop_dist*move_dir),time, 0, time); wait time; } self StopLoopSound(); stop_sound = movable_cover_get_sound("stop"); if(IsDefined(stop_sound)) self PlaySound(stop_sound); if(IsDefined(self.animate_ent) && IsDefined(level.movable_cover_move_anim[self.movable_type]["idle"])) { self.animate_ent scriptmodelPlayanim(level.movable_cover_move_anim[self.movable_type]["idle"]); } if(stay && self movable_cover_at_goal(move_to.origin)) { self.stay = true; } if(self.updatePaths) self DisconnectPaths(); self movable_cover_connect_traversals(); self.moving = false; self notify( "move_end" ); } } movable_cover_connect_traversals() { self movable_cover_disconnect_traversals(); foreach(node in self.traverse_nodes) { switch(node.node_type) { case "closest": node.connected_to = getClosest(node.origin, node.connected_nodes); break; case "radius": case "radius3d": //fallthrough dist = Distance(node.origin, node.test_origin); if(dist<=node.test_radius) node.connected_to = node.connected_nodes[0]; break; case "radius2d": dist2d = Distance2d(node.origin, node.test_origin); if(dist2d<=node.test_radius) node.connected_to = node.connected_nodes[0]; break; default: break; } if(IsDefined(node.connected_to)) { ConnectNodePair(node, node.connected_to); } } } movable_cover_disconnect_traversals() { foreach(node in self.traverse_nodes) { if(IsDefined(node.connected_to)) { DisconnectNodePair(node, node.connected_to); node.connected_to = undefined; } } } movable_cover_get_sound(type) { if(!IsDefined(level.movable_cover_move_sounds[self.movable_type])) return undefined; return level.movable_cover_move_sounds[self.movable_type][type]; } movable_cover_wait_for_user_or_timeout(time) { self endon("new_user"); wait time; } movable_cover_calc_move_speed_scale(current_time, move_time, accel_time, decel_time) { if(!IsDefined(accel_time)) accel_time = 0; if(!IsDefined(decel_time)) decel_time = 0; if(current_time >= move_time || current_time <= 0) { return 0; } else if(current_time < accel_time) { return 1 - ((accel_time - current_time) / accel_time); } else if(current_time > (move_time - decel_time)) { return 1 - ((current_time - (move_time - decel_time)) / decel_time); } else { return 1; } } movable_cover_is_pushed(player, trigger, move_dir) { //We have the player check so that the trigger doesn't error out when a dog enters. if( !IsDefined( player ) || !IsReallyAlive( player ) || !IsPlayer( player) ) return false; if(!movable_cover_is_touched(trigger, player)) return false; if(player IsMantling()) return false; stance = player GetStance(); if(!array_contains(self.stances, stance)) return false; if(self.requires_push) { player_move_dir = player GetNormalizedMovement(); player_move_dir = RotateVector(player_move_dir, -1*player.angles); player_move_dir = VectorNormalize((player_move_dir[0], -1*player_move_dir[1], 0)); dot = VectorDot(move_dir, player_move_dir); return dot>0.2; } else { return true; } } movable_cover_is_touched(trigger, player) { return IsDefined( player ) && isReallyAlive( player ) && player IsTouching(trigger); } movable_cover_move_delay(delay, player, trigger, move_dir) { endTime = (delay*1000)+GetTime(); while(1) { if( !IsDefined( player ) || !isReallyAlive( player ) ) return false; if(player IsMantling()) return false; if(!movable_cover_is_pushed(player, trigger, move_dir)) return false; if(self.moving) return false; if(getTime()>=endTime) return true; wait .05; } } movable_cover_at_goal(goal) { distSqr = DistanceSquared(self.origin, goal); return distSqr<=(self.goal_radius*self.goal_radius); } // Make movers unmantleable while moving - avoids animating into solid architecture movable_cover_mantlebrush_think( mantlebrush )// self = mover { self endon("death"); while(1) { self waittill( "move_start" ); if ( IsDefined( mantlebrush ) ) { mantlebrush.old_contents = mantlebrush SetContents( 0 ); mantlebrush Hide(); } self waittill( "move_end" ); if ( IsDefined( mantlebrush ) ) { mantlebrush Show(); mantlebrush SetContents( mantlebrush.old_contents ); } } }