Advertisement
Guest User

Untitled

a guest
Jun 23rd, 2017
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.36 KB | None | 0 0
  1. #include maps\mp\_utility;
  2. #include common_scripts\utility;
  3.  
  4. init()
  5. {
  6. level.friendlyDogModel = "german_shepherd";
  7. level.enemyDogModel = "german_shepherd_black";
  8.  
  9. precacheModel(level.friendlyDogModel);
  10. precacheModel(level.enemyDogModel);
  11. precacheItem("dog_bite_mp");
  12. precacheShellshock("dog_bite");
  13.  
  14. level.maxDogsAttackingPerPlayer = 2;
  15. level.spawnTimeWaitMin = 2;
  16. level.spawnTimeWaitMax = 5;
  17.  
  18. level.no_dogs = false;
  19.  
  20. init_node_arrays();
  21.  
  22. if ( level.no_pathnodes )
  23. level.no_dogs = true;
  24.  
  25. regenTime = 5;
  26. level.dogHealth_RegularRegenDelay = regenTime * 1000;
  27. level.dogHealthRegenDisabled = (level.dogHealth_RegularRegenDelay <= 0);
  28.  
  29. dog_dvar_update();
  30. thread dog_dvar_updater();
  31. thread dog_usage_init();
  32.  
  33. thread init_all_preexisting_dogs();
  34.  
  35. // create_dogs();
  36. }
  37.  
  38. pick_random_nodes( from, count )
  39. {
  40. to = [];
  41.  
  42. if ( from.size < count )
  43. {
  44. to = from;
  45. }
  46. else
  47. {
  48. for ( i = 0; i < count; i++ )
  49. {
  50. to[i] = from[randomInt(from.size)];
  51. }
  52. }
  53.  
  54. return to;
  55. }
  56.  
  57. init_node_arrays()
  58. {
  59. nodes = getallnodes();
  60.  
  61. pathnodes = [];
  62.  
  63. for ( i = 0; i < nodes.size; i++ )
  64. {
  65. // anything with a scriptworthy is automatically a non-patrol node
  66. if ( isdefined(nodes[i].script_noteworthy) /* || nodes[i].script_noteworthy != "" */)
  67. continue;
  68.  
  69. if ( isdefined(nodes[i].targetname) && nodes[i].targetname == "traverse" )
  70. continue;
  71.  
  72. pathnodes[pathnodes.size] = nodes[i];
  73. }
  74.  
  75. if ( pathnodes.size == 0 )
  76. {
  77. level.no_pathnodes = true;
  78. }
  79. else
  80. {
  81. level.no_pathnodes = false;
  82. }
  83.  
  84. level.patrolnodes = [];
  85.  
  86. level.patrolnodes = pick_random_nodes( pathnodes, 200 );
  87.  
  88. level.dogspawnnodes = [];
  89. level.dogspawnnodes = getnodearray( "spawn", "script_noteworthy");
  90.  
  91. if ( level.dogspawnnodes.size == 0 )
  92. {
  93. /#
  94. println("DOG PATHING: Could not find spawn nodes");
  95. #/
  96. // pick a random set of spawn nodes so we do not tax the spawn logic to much
  97. level.dogspawnnodes = pick_random_nodes( pathnodes, 20 );
  98. }
  99.  
  100. level.dogexitnodes = [];
  101. level.dogexitnodes = getnodearray( "exit", "script_noteworthy");
  102.  
  103. if ( level.dogexitnodes.size == 0 )
  104. {
  105. /#
  106. println("DOG PATHING: Could not find exit nodes");
  107. #/
  108. // pick a random set of spawn nodes so we do not tax the spawn logic to much
  109. level.dogexitnodes = pick_random_nodes( pathnodes, 20 );
  110. }
  111. }
  112.  
  113. dog_dvar_update()
  114. {
  115. level.dog_time = dog_get_dvar_int("scr_dog_time", "60" );
  116. level.dog_health = dog_get_dvar_int("scr_dog_health", "100" );
  117. level.dog_count = dog_get_dvar_int("scr_dog_count", "8" );
  118. level.dog_count_max_at_once = dog_get_dvar_int("scr_dog_max_at_once", "4" );
  119.  
  120. if ( level.dog_count < level.dog_count_max_at_once )
  121. {
  122. level.dog_count_max_at_once = level.dog_count;
  123. }
  124.  
  125. level.dog_debug = dog_get_dvar_int("debug_dogs", "0" );
  126. level.dog_debug_sound = dog_get_dvar_int("debug_dog_sound", "0" );
  127. level.dog_debug_anims = dog_get_dvar_int("debug_dog_anims", "0" );
  128. level.dog_debug_anims_ent = dog_get_dvar_int("debug_dog_anims_ent", "0" );
  129. level.dog_debug_turns = dog_get_dvar_int("debug_dog_turns", "0" );
  130. level.dog_debug_orient = dog_get_dvar_int("debug_dog_orient", "0" );
  131. level.dog_debug_usage = dog_get_dvar_int("debug_dog_usage", "1" );
  132. }
  133.  
  134. dog_dvar_updater()
  135. {
  136. dogs_in_the_bsp = count_preexisting_dogs();
  137. while(1)
  138. {
  139. dog_dvar_update();
  140.  
  141. // 16 is max allowed by engine
  142. if ( level.dog_count + dogs_in_the_bsp > 16 )
  143. {
  144. level.dog_count = 16 - dogs_in_the_bsp;
  145. }
  146. wait (1);
  147. }
  148. }
  149.  
  150. count_preexisting_dogs()
  151. {
  152. dogs = getentarray( "actor_enemy_dog", "classname" );
  153.  
  154. alive_count = 0;
  155. for ( i = 0; i < dogs.size; i ++ )
  156. {
  157. if ( !isdefined(dogs[i]) )
  158. continue;
  159.  
  160. if ( !isai(dogs[i]) )
  161. continue;
  162.  
  163. alive_count++;
  164. }
  165.  
  166. return alive_count;
  167. }
  168.  
  169. init_all_preexisting_dogs()
  170. {
  171. array_thread( getentarray( "actor_enemy_dog", "classname" ), ::preexisting_init_dog );
  172. }
  173.  
  174. preexisting_init_dog()
  175. {
  176. self init_dog();
  177. }
  178.  
  179. dog_set_model()
  180. {
  181. self setModel(level.friendlyDogModel);
  182. self setEnemyModel(level.enemyDogModel);
  183. }
  184.  
  185. init_dog()
  186. {
  187. if ( !isai(self) )
  188. return;
  189.  
  190. self.aiteam = "axis";
  191.  
  192. self.animTree = "dog.atr";
  193. self.type = "dog";
  194. self.accuracy = 0.2;
  195. self.health = level.dog_health;
  196. self.maxhealth = level.dog_health; // this currently does not hook to code maxhealth
  197. self.aiweapon = "dog_bite_mp";
  198. self.secondaryweapon = "";
  199. self.sidearm = "";
  200. self.grenadeAmmo = 0;
  201. self.goalradius = 128;
  202. self.noDodgeMove = true;
  203. self.ignoreSuppression = true;
  204. self.suppressionThreshold = 1;
  205. self.disableArrivals = false;
  206. self.pathEnemyFightDist = 512;
  207.  
  208. self.meleeAttackDist = 102;
  209.  
  210. self dog_set_model();
  211.  
  212. self thread dogHealthRegen();
  213.  
  214. self thread selfDefenseChallenge();
  215. }
  216.  
  217. get_spawn_node( team )
  218. {
  219. if ( !level.teambased )
  220. return dog_pick_node_away_from_enemy(level.dogspawnnodes, team);
  221.  
  222. return dog_pick_node_near_team(level.dogspawnnodes, team);
  223. }
  224.  
  225. dog_watch_for_owner_team_change(owner)
  226. {
  227. self endon("death");
  228. owner endon("disconnect");
  229.  
  230. while(1)
  231. {
  232. owner waittill("joined_team");
  233.  
  234. if ( owner.pers["team"] != self.aiteam )
  235. {
  236. self clearentityowner();
  237. self notify("clear_owner");
  238. return;
  239. }
  240. }
  241. }
  242.  
  243. dog_set_owner( owner, team, requiredDeathCount )
  244. {
  245. /#
  246. // no owner so he attacks the person who called him in
  247. if ( level.dog_debug )
  248. return;
  249. #/
  250.  
  251. if ( !isdefined( owner ) )
  252. return;
  253.  
  254. // if the owner switches teams while dogs are still spawning
  255. // do not set the owner
  256. if ( level.teambased && isplayer(owner) && owner.pers["team"] != team )
  257. return;
  258.  
  259. self setentityowner(owner);
  260.  
  261. self.requiredDeathCount = requiredDeathCount;
  262.  
  263. self thread dog_watch_for_owner_team_change(owner);
  264.  
  265. self endon("death");
  266. owner waittill("disconnect");
  267.  
  268. self clearentityowner();
  269. }
  270.  
  271. dog_create_spawn_influencer()
  272. {
  273. self maps\mp\gametypes\_spawning::create_dog_influencers();
  274. }
  275.  
  276. dog_manager_spawn_dog( owner, team, spawn_node, index, requiredDeathCount )
  277. {
  278. dog = level.dog_spawner spawnactor();
  279.  
  280. dog forceteleport(spawn_node.origin, spawn_node.angles);
  281. dog setgoalnode( spawn_node );
  282. dog.spawnnode = spawn_node;
  283. dog show();
  284.  
  285. dog init_dog();
  286. dog dog_set_team(team);
  287. dog dog_set_model();
  288. dog dog_create_spawn_influencer();
  289. dog thread dog_set_owner(owner, team, requiredDeathCount );
  290.  
  291. dog thread dog_usage(index);
  292. dog thread dog_owner_kills();
  293. dog thread dog_clean_up();
  294. dog thread dog_notify_level_on_death();
  295. dog dog_thread_behavior_function();
  296.  
  297.  
  298. return dog;
  299. }
  300.  
  301. get_debug_team( team )
  302. {
  303. /#
  304. if ( level.teambased )
  305. {
  306. otherteam = getotherteam(team);
  307. if ( level.dog_debug )
  308. return otherteam;
  309. }
  310. #/
  311.  
  312. if ( !level.teambased )
  313. return "free";
  314.  
  315. return team;
  316. }
  317.  
  318. dog_manager_spawn_dogs( team, enemyTeam, deathCount )
  319. {
  320. // this can hit if the round ends as the dogs are getting called in
  321. level endon("dogs done");
  322. level endon("dogs leaving");
  323. self endon("disconnect");
  324.  
  325. if ( level.no_dogs )
  326. return;
  327.  
  328. team = get_debug_team(team);
  329.  
  330. requiredDeathCount = deathCount;
  331.  
  332. level.dog_spawner = getent("dog_spawner","targetname" );
  333.  
  334. if ( !isdefined( level.dog_spawner ) )
  335. return;
  336.  
  337. level.dogs = [];
  338.  
  339. level thread dog_manager_game_ended();
  340. level thread dog_manager_dog_alive_tracker();
  341. level thread dog_manager_dog_time_limit();
  342. level thread dog_usage_monitor();
  343.  
  344. for ( i = 0; i < level.dog_count_max_at_once; i++ )
  345. {
  346. node = self get_spawn_node( team );
  347.  
  348. level.dogs[i] = dog_manager_spawn_dog( self, team, node, i, requiredDeathCount );
  349.  
  350. wait ( randomfloat( level.spawnTimeWaitMin, level.spawnTimeWaitMax ) );
  351. }
  352.  
  353. level thread dog_manager_spawn_more_dogs_on_death( self, level.dog_count - level.dog_count_max_at_once, team );
  354. }
  355.  
  356. dog_manager_spawn_more_dogs_on_death( owner, count, team )
  357. {
  358. level endon("dogs done");
  359. level endon("dogs leaving");
  360.  
  361. while( count > 0 )
  362. {
  363. level waittill("dog died");
  364.  
  365. // wait a bit before sending in the next dog
  366. wait ( randomfloat( level.spawnTimeWaitMin, level.spawnTimeWaitMax ) );
  367.  
  368. node = get_spawn_node( team );
  369. level.dogs[level.dogs.size] = dog_manager_spawn_dog( owner, team, node, level.dogs.size );
  370. count -= 1;
  371. }
  372.  
  373. /#
  374. iprintln("All dogs spawned");
  375. #/
  376. level notify("all dogs spawned");
  377. }
  378.  
  379. dog_manager_dog_time_limit()
  380. {
  381. level endon("dogs done");
  382. level endon("dogs leaving");
  383. wait( level.dog_time );
  384.  
  385. /#
  386. dog_debug_print( "time limit hit notify dogs leaving" );
  387. #/
  388. // this will shut this thread down
  389. level notify("dogs leaving");
  390. }
  391.  
  392. dog_cleanup_wait( wait_for, notify_name )
  393. {
  394. self endon( notify_name );
  395. self waittill( wait_for );
  396. self notify( notify_name, wait_for );
  397. }
  398.  
  399. dog_cleanup_waiter()
  400. {
  401. self thread dog_cleanup_wait( "all dogs spawned", "start_tracker");
  402. self thread dog_cleanup_wait( "dogs leaving", "start_tracker" );
  403.  
  404. self waittill( "start_tracker", wait_for );
  405. /#
  406. self dog_debug_print("starting dog_manager_dog_alive_tracker reason " + wait_for );
  407. #/
  408. }
  409.  
  410. dog_manager_dog_alive_tracker()
  411. {
  412. level dog_cleanup_waiter();
  413.  
  414. while (1)
  415. {
  416. alive_count = 0;
  417. for ( i = 0; i < level.dogs.size; i ++ )
  418. {
  419. if ( !isdefined(level.dogs[i]) )
  420. continue;
  421.  
  422. if ( !isalive(level.dogs[i]) )
  423. continue;
  424.  
  425. alive_count++;
  426. }
  427.  
  428. if ( alive_count == 0 )
  429. {
  430. wait(1);
  431. dog_manager_delete_dogs();
  432. level notify("dogs done");
  433. return;
  434. }
  435.  
  436. wait (1);
  437. }
  438. }
  439.  
  440. dog_manager_delete_dogs()
  441. {
  442. for ( i = 0; i < level.dogs.size; i ++ )
  443. {
  444. if ( !isdefined(level.dogs[i]) )
  445. continue;
  446.  
  447. level.dogs[i] delete();
  448. }
  449.  
  450. level.dogs = undefined;
  451. }
  452.  
  453. dog_manager_game_ended()
  454. {
  455. level waittill("game_ended");
  456. make_all_dogs_leave();
  457. }
  458.  
  459. make_all_dogs_leave()
  460. {
  461. /#
  462. dog_debug_print( "make_all_dogs_leave notify dogs leaving" );
  463. #/
  464. level notify("dogs leaving");
  465. }
  466.  
  467. dog_set_team( team )
  468. {
  469. self.aiteam = team;
  470. }
  471.  
  472. dog_clean_up()
  473. {
  474. self endon("death");
  475. self endon("leaving");
  476. level waittill("dogs leaving");
  477.  
  478. thread dog_leave();
  479. }
  480.  
  481. dog_notify_level_on_death()
  482. {
  483. self endon("leaving");
  484. self waittill("death");
  485.  
  486. // do not access self past this point as its not valid
  487.  
  488. level notify("dog died");
  489. }
  490.  
  491. dog_thread_behavior_function()
  492. {
  493. self thread dog_patrol_when_no_enemy();
  494. // self thread dog_attack_when_enemy();
  495. }
  496.  
  497. dog_leave()
  498. {
  499. self notify("leaving");
  500.  
  501. self thread dog_leave_failsafe();
  502.  
  503. // have them run to an exit node
  504. self clearentitytarget();
  505. self.ignoreall = true;
  506. self.goalradius = 30;
  507. self setgoalnode( self dog_get_exit_node() );
  508.  
  509. self waittill("goal");
  510. self delete();
  511. }
  512.  
  513. dog_leave_failsafe()
  514. {
  515. self endon("death");
  516.  
  517. start_origin = self.origin;
  518.  
  519. wait(2);
  520.  
  521. if ( distance( start_origin, self.origin ) < 10 )
  522. {
  523. /#
  524. println( "DOG DELETE FAILSAFE: Dog appears to be stuck at " + self.origin );
  525. #/
  526. self delete();
  527. return;
  528. }
  529.  
  530. wait(20);
  531. /#
  532. println( "DOG DELETE FAILSAFE: Dog has not gotten to it's delete point after 20 seconds. Currently at " + self.origin );
  533. #/
  534. self delete();
  535. }
  536.  
  537.  
  538. dog_patrol_when_no_enemy()
  539. {
  540. self endon("death");
  541. self endon("leaving");
  542.  
  543. while(1)
  544. {
  545. if ( !isdefined(self.enemy) )
  546. {
  547. self dog_debug_print( "no enemy starting patrol" );
  548. self thread dog_patrol();
  549. }
  550.  
  551. self waittill("enemy");
  552. }
  553. }
  554.  
  555. dog_patrol_wait( wait_for, notify_name )
  556. {
  557. self endon("attacking");
  558. dog_wait( wait_for, notify_name );
  559. }
  560.  
  561. dog_wait( wait_for, notify_name )
  562. {
  563. self endon("death");
  564. self endon("leaving");
  565. self endon( notify_name );
  566.  
  567. self waittill( wait_for );
  568. self notify( notify_name, wait_for );
  569. }
  570.  
  571. dog_patrol_path_waiter()
  572. {
  573. self thread dog_patrol_wait( "bad_path", "next_patrol_point");
  574. self thread dog_patrol_wait( "goal", "next_patrol_point" );
  575.  
  576. self waittill( "next_patrol_point", wait_for );
  577. /#
  578. self dog_debug_print("ending patrol wait recieved " + wait_for );
  579. #/
  580. }
  581.  
  582. dog_patrol()
  583. {
  584. self endon("death");
  585. self endon("enemy");
  586. self endon("leaving");
  587. self endon("attacking");
  588. self notify("on patrol");
  589.  
  590. self dog_patrol_debug();
  591.  
  592. while(1)
  593. {
  594. node = level.patrolnodes[randomInt(level.patrolnodes.size)];
  595.  
  596. // ignore all nodes with a script_noteworthy on them
  597. if ( !isdefined( node.script_noteworthy ) )
  598. {
  599. /#
  600. self dog_debug_print("patroling to node at " + node.origin );
  601. #/
  602. self setgoalnode( node );
  603. self dog_patrol_path_waiter();
  604. }
  605. }
  606. }
  607.  
  608. dog_wait_print( wait_for )
  609. {
  610. /#
  611. self endon("kill dog_wait_prints");
  612.  
  613. self waittill( wait_for );
  614. self notify("kill dog_wait_prints");
  615. self dog_debug_print( "PATROL ENDING " + wait_for );
  616. #/
  617. }
  618.  
  619. dog_patrol_debug()
  620. {
  621. self thread dog_wait_print("death");
  622. self thread dog_wait_print("enemy");
  623. self thread dog_wait_print("leaving");
  624. self thread dog_wait_print("attacking");
  625. }
  626.  
  627. dog_get_dvar_int( dvar, def )
  628. {
  629. return int( dog_get_dvar( dvar, def ) );
  630. }
  631.  
  632. // dvar set/fetch/check
  633. dog_get_dvar( dvar, def )
  634. {
  635. if ( getdvar( dvar ) != "" )
  636. return getdvarfloat( dvar );
  637. else
  638. {
  639. setdvar( dvar, def );
  640. return def;
  641. }
  642. }
  643.  
  644. dog_usage_init()
  645. {
  646. level.dog_usage = [];
  647.  
  648. for ( index = 0; index < level.dog_count; index++ )
  649. {
  650. level.dog_usage[index] = spawnStruct();
  651. level.dog_usage[index].spawn_time = 0;
  652. level.dog_usage[index].death_time = 0;
  653. level.dog_usage[index].kills = 0;
  654. level.dog_usage[index].died = false;
  655. }
  656. }
  657.  
  658. dog_usage_monitor()
  659. {
  660. start_time = GetTime();
  661.  
  662. level waittill("dogs done");
  663.  
  664. index = 0;
  665. total_kills = 0;
  666. last_alive = 0;
  667. all_dead = true;
  668. alive_count = 0;
  669. never_spawned_count = 0;
  670. total_count = 0;
  671.  
  672. for ( index = 0; index < level.dog_count; index++ )
  673. {
  674. total_count++;
  675.  
  676. if ( level.dog_usage[index].spawn_time == 0 )
  677. {
  678. never_spawned_count++;
  679. continue;
  680. }
  681. else if ( !level.dog_usage[index].died )
  682. {
  683. alive_count++;
  684. all_dead = false;
  685. }
  686.  
  687. seconds = (level.dog_usage[index].death_time - level.dog_usage[index].spawn_time) / 1000;
  688. if ( seconds > last_alive )
  689. {
  690. last_alive = seconds;
  691. }
  692.  
  693. total_kills += level.dog_usage[index].kills;
  694. }
  695.  
  696. /#
  697. seconds = (GetTime() - start_time) / 1000;
  698. msg = "Dogs- Time: " + seconds + " Kills: " + total_kills + " Last: " + last_alive;
  699.  
  700. // make sure that the dogs have printed everything
  701. wait (1);
  702. iprintln( msg );
  703. println( msg );
  704. #/
  705. }
  706.  
  707. dog_usage(index)
  708. {
  709. level.dog_usage[index].spawn_time = GetTime();
  710. level.dog_usage[index].death_time = 0;
  711. level.dog_usage[index].kills = 0;
  712. level.dog_usage[index].died = false;
  713.  
  714. self thread dog_usage_kills(index);
  715. self thread dog_usage_time_alive(index);
  716. }
  717.  
  718. dog_usage_kills(index)
  719. {
  720. self endon("death");
  721.  
  722. while(1)
  723. {
  724. self waittill("killed", player);
  725. level.dog_usage[index].kills++;
  726. }
  727. }
  728.  
  729. dog_owner_kills(index)
  730. {
  731. if ( !isdefined( self.script_owner ) )
  732. return;
  733.  
  734. self endon("clear_owner");
  735. self endon("death");
  736. self.script_owner endon("disconnect");
  737.  
  738. while(1)
  739. {
  740. self waittill("killed", player);
  741. self.script_owner notify( "dog_handler" );
  742. }
  743. }
  744.  
  745. dog_usage_time_alive(index)
  746. {
  747. self endon("leaving");
  748.  
  749. self waittill("death");
  750. level.dog_usage[index].death_time = GetTime();
  751. level.dog_usage[index].died = true;
  752.  
  753. seconds = (level.dog_usage[index].death_time - level.dog_usage[index].spawn_time) / 1000 ;
  754. /#
  755. iprintln( "Dog#" + index + " killed. Alive for: "+ seconds + " seconds. Kills: " + level.dog_usage[index].kills );
  756. println( "Dog#" + index + " killed. Alive for: "+ seconds + " seconds. Kills: " + level.dog_usage[index].kills );
  757. #/
  758. }
  759.  
  760.  
  761. dogHealthRegen()
  762. {
  763. self endon("death");
  764. self endon("end_healthregen");
  765.  
  766. if ( self.health <= 0 )
  767. {
  768. assert( !isalive( self ) );
  769. return;
  770. }
  771.  
  772. maxhealth = self.health;
  773. oldhealth = maxhealth;
  774. dog = self;
  775. health_add = 0;
  776.  
  777. regenRate = 0.1; // 0.017;
  778. veryHurt = false;
  779.  
  780. lastSoundTime_Recover = 0;
  781. hurtTime = 0;
  782. newHealth = 0;
  783.  
  784. for (;;)
  785. {
  786. wait (0.05);
  787. if (dog.health == maxhealth)
  788. {
  789. veryHurt = false;
  790. continue;
  791. }
  792.  
  793. if (dog.health <= 0)
  794. return;
  795.  
  796. wasVeryHurt = veryHurt;
  797. ratio = dog.health / maxHealth;
  798. if (ratio <= 0.55)
  799. {
  800. veryHurt = true;
  801. if (!wasVeryHurt)
  802. {
  803. hurtTime = gettime();
  804. }
  805. }
  806.  
  807. if (dog.health >= oldhealth)
  808. {
  809. if (gettime() - hurttime < level.dogHealth_RegularRegenDelay)
  810. continue;
  811.  
  812. if ( level.dogHealthRegenDisabled )
  813. continue;
  814.  
  815. if (veryHurt)
  816. {
  817. newHealth = ratio;
  818. if (gettime() > hurtTime + 3000)
  819. newHealth += regenRate;
  820. }
  821. else
  822. newHealth = 1;
  823.  
  824. if ( newHealth >= 1.0 )
  825. {
  826. newHealth = 1.0;
  827. }
  828.  
  829. if (newHealth <= 0)
  830. {
  831. // dog is dead
  832. return;
  833. }
  834.  
  835. dog setnormalhealth (newHealth);
  836. oldhealth = dog.health;
  837. continue;
  838. }
  839.  
  840. oldhealth = dog.health;
  841.  
  842. health_add = 0;
  843. hurtTime = gettime();
  844. }
  845. }
  846.  
  847.  
  848. selfDefenseChallenge()
  849. {
  850. self waittill ("death", attacker);
  851.  
  852. if ( isdefined( attacker ) && isPlayer( attacker ) )
  853. {
  854. if (isdefined ( self.script_owner ) && self.script_owner == attacker)
  855. return;
  856. if ( level.teambased && isdefined ( self.script_owner ) && self.script_owner.team == attacker.team )
  857. return;
  858.  
  859. attacker notify ("selfdefense_dog");
  860. }
  861.  
  862. }
  863.  
  864. dog_get_exit_node()
  865. {
  866. return getclosest( self.origin, level.dogexitnodes );
  867. }
  868.  
  869. dog_debug_print( message )
  870. {
  871. /#
  872. if ( level.dog_debug )
  873. {
  874. if ( isai( self ) )
  875. {
  876. println( " " + gettime() + " DOG " + self getentnum() + ": " + message );
  877. }
  878. else
  879. {
  880. println( " " + gettime() + " DOGS: " + message );
  881. }
  882. }
  883. #/
  884. }
  885.  
  886. // ================================================
  887.  
  888. getAllOtherPlayers()
  889. {
  890. aliveplayers = [];
  891.  
  892. // Make a list of fully connected, non-spectating, alive players
  893. for(i = 0; i < level.players.size; i++)
  894. {
  895. if ( !isdefined( level.players[i] ) )
  896. continue;
  897. player = level.players[i];
  898.  
  899. if ( player.sessionstate != "playing" || player == self )
  900. continue;
  901.  
  902. aliveplayers[aliveplayers.size] = player;
  903. }
  904. return aliveplayers;
  905. }
  906.  
  907. dog_pick_node_near_team( nodes, team )
  908. {
  909. // There are no valid nodes in the map
  910. if(!isdefined(nodes))
  911. return undefined;
  912.  
  913. if ( !level.teambased )
  914. return dog_pick_node_away_from_enemy(level.dogspawnnodes, team);
  915.  
  916. //prof_begin("basic_spawnlogic");
  917.  
  918. initWeights(nodes);
  919. update_all_nodes( nodes, team );
  920.  
  921. //prof_begin(" getteams");
  922. obj = spawnstruct();
  923. getAllAlliedAndEnemyPlayers(obj, team);
  924. //prof_end(" getteams");
  925.  
  926. numplayers = obj.allies.size + obj.enemies.size;
  927.  
  928. alliedDistanceWeight = 2;
  929. dogDistanceWeight = 3;
  930.  
  931. //prof_begin(" sumdists");
  932. myTeam = team;
  933.  
  934. enemyTeam = getOtherTeam( myTeam );
  935. for (i = 0; i < nodes.size; i++)
  936. {
  937. node = nodes[i];
  938.  
  939. node.weight = 0;
  940.  
  941. if ( node.numPlayersAtLastUpdate > 0 )
  942. {
  943. allyDistSum = node.distSum[ myTeam ];
  944. enemyDistSum = node.distSum[ enemyTeam ];
  945.  
  946. // high enemy distance is good, high ally distance is bad
  947. node.weight = (enemyDistSum - alliedDistanceWeight*allyDistSum) / node.numPlayersAtLastUpdate;
  948. }
  949.  
  950. if ( node.numDogsAtLastUpdate > 0 )
  951. {
  952. dogDistSum = node.distSum[ "dogs" ];
  953.  
  954. // high ally distance is bad
  955. node.weight -= (dogDistSum*dogDistSum) / node.numDogsAtLastUpdate;
  956. }
  957. }
  958. //prof_end(" sumdists");
  959.  
  960. //prof_end("basic_spawnlogic");
  961.  
  962. //prof_begin("complex_spawnlogic");
  963.  
  964. avoidSpawnReuse(nodes);
  965. avoidEnemies(nodes, team, true);
  966.  
  967. //prof_end("complex_spawnlogic");
  968.  
  969. result = dog_pick_node_final(nodes, team, obj.enemies);
  970.  
  971. return result;
  972. }
  973.  
  974.  
  975. dog_pick_node_away_from_enemy(nodes, team)
  976. {
  977. // There are no valid nodes in the map
  978. if(!isdefined(nodes))
  979. return undefined;
  980.  
  981. initWeights(nodes);
  982. update_all_nodes( nodes, team );
  983.  
  984. aliveplayers = getAllOtherPlayers();
  985.  
  986. // new logic: we want most players near idealDist units away.
  987. // players closer than badDist units will be considered negatively
  988. idealDist = 1600;
  989. badDist = 1200;
  990.  
  991. if (aliveplayers.size > 0)
  992. {
  993. for (i = 0; i < nodes.size; i++)
  994. {
  995. totalDistFromIdeal = 0;
  996. nearbyBadAmount = 0;
  997. for (j = 0; j < aliveplayers.size; j++)
  998. {
  999. dist = distance(nodes[i].origin, aliveplayers[j].origin);
  1000.  
  1001. if (dist < badDist)
  1002. nearbyBadAmount += (badDist - dist) / badDist;
  1003.  
  1004. distfromideal = abs(dist - idealDist);
  1005. totalDistFromIdeal += distfromideal;
  1006. }
  1007. avgDistFromIdeal = totalDistFromIdeal / aliveplayers.size;
  1008.  
  1009. wellDistancedAmount = (idealDist - avgDistFromIdeal) / idealDist;
  1010.  
  1011. // wellDistancedAmount is between -inf and 1, 1 being best (likely around 0 to 1)
  1012. // nearbyBadAmount is between 0 and inf,
  1013. // and it is very important that we get a bad weight if we have a high nearbyBadAmount.
  1014.  
  1015. nodes[i].weight = wellDistancedAmount - nearbyBadAmount * 2 + randomfloat(.2);
  1016. }
  1017. }
  1018.  
  1019. avoidSpawnReuse(nodes);
  1020. avoidEnemies(nodes, team, true);
  1021.  
  1022. return dog_pick_node_final(nodes, team, aliveplayers);
  1023. }
  1024.  
  1025. dog_pick_node_random( nodes, team )
  1026. {
  1027. // There are no valid nodes in the map
  1028. if(!isdefined(nodes))
  1029. return undefined;
  1030.  
  1031. // randomize order
  1032. for(i = 0; i < nodes.size; i++)
  1033. {
  1034. j = randomInt(nodes.size);
  1035. node = nodes[i];
  1036. nodes[i] = nodes[j];
  1037. nodes[j] = node;
  1038. }
  1039.  
  1040. return dog_pick_node_final(nodes, team, undefined, false);
  1041. }
  1042.  
  1043. // selects a node, preferring ones with heigher weights (or toward the beginning of the array if no weights).
  1044. // also does final things like setting self.lastnode to the one chosen.
  1045. // this takes care of avoiding telefragging, so it doesn't have to be considered by any other function.
  1046. dog_pick_node_final( nodes, team, enemies, useweights )
  1047. {
  1048. //prof_begin( "dog_pick_node_final" );
  1049.  
  1050. bestnode = undefined;
  1051.  
  1052. if ( !isdefined( nodes ) || nodes.size == 0 )
  1053. return undefined;
  1054.  
  1055. if ( !isdefined( useweights ) )
  1056. useweights = true;
  1057.  
  1058. if ( useweights )
  1059. {
  1060. // choose node with best weight
  1061. // (if a tie, choose randomly from the best)
  1062. bestnode = getBestWeightedNode( nodes, team, enemies );
  1063. }
  1064. else
  1065. {
  1066. // (only place we actually get here from is dog_pick_node_random() )
  1067. // no weights. prefer nodes toward beginning of array
  1068. for ( i = 0; i < nodes.size; i++ )
  1069. {
  1070. if ( positionWouldTelefrag( nodes[i].origin ) )
  1071. continue;
  1072.  
  1073. bestnode = nodes[i];
  1074. break;
  1075. }
  1076. }
  1077.  
  1078. if ( !isdefined( bestnode ) )
  1079. {
  1080. // couldn't find a useable node! all will telefrag.
  1081. if ( useweights )
  1082. {
  1083. // at this point, forget about weights. just take a random one.
  1084. bestnode = nodes[randomint(nodes.size)];
  1085. }
  1086. else
  1087. {
  1088. bestnode = nodes[0];
  1089. }
  1090. }
  1091.  
  1092. self finalizeNodeChoice( bestnode );
  1093.  
  1094. //prof_end( "dog_pick_node_final" );
  1095.  
  1096. return bestnode;
  1097. }
  1098.  
  1099. getBestWeightedNode( nodes, team, enemies )
  1100. {
  1101. maxSightTracedNodes = 3;
  1102. for ( try = 0; try <= maxSightTracedNodes; try++ )
  1103. {
  1104. bestnodes = [];
  1105. bestweight = undefined;
  1106. bestnode = undefined;
  1107. for ( i = 0; i < nodes.size; i++ )
  1108. {
  1109. if ( !isdefined( bestweight ) || nodes[i].weight > bestweight )
  1110. {
  1111. if ( positionWouldTelefrag( nodes[i].origin ) )
  1112. continue;
  1113.  
  1114. bestnodes = [];
  1115. bestnodes[0] = nodes[i];
  1116. bestweight = nodes[i].weight;
  1117. }
  1118. else if ( nodes[i].weight == bestweight )
  1119. {
  1120. if ( positionWouldTelefrag( nodes[i].origin ) )
  1121. continue;
  1122.  
  1123. bestnodes[bestnodes.size] = nodes[i];
  1124. }
  1125. }
  1126. if ( bestnodes.size == 0 )
  1127. return undefined;
  1128.  
  1129. // pick randomly from the available nodes with the best weight
  1130. bestnode = bestnodes[randomint( bestnodes.size )];
  1131.  
  1132. if ( try == maxSightTracedNodes )
  1133. return bestnode;
  1134.  
  1135. if ( isdefined( bestnode.lastSightTraceTime ) && bestnode.lastSightTraceTime == gettime() )
  1136. return bestnode;
  1137.  
  1138. if ( !lastMinuteSightTraces( bestnode, team, enemies ) )
  1139. return bestnode;
  1140.  
  1141. penalty = getLosPenalty();
  1142. bestnode.weight -= penalty;
  1143.  
  1144. bestnode.lastSightTraceTime = gettime();
  1145. }
  1146. }
  1147.  
  1148. finalizeNodeChoice( node )
  1149. {
  1150. time = getTime();
  1151.  
  1152. self.lastnode = node;
  1153. self.lastspawntime = time;
  1154. node.lastspawneddog = self;
  1155. node.lastspawntime = time;
  1156. }
  1157.  
  1158. getLosPenalty()
  1159. {
  1160. return 100000;
  1161. }
  1162.  
  1163. lastMinuteSightTraces( node, dog_team, enemies )
  1164. {
  1165. //prof_begin("lastMinuteSightTraces");
  1166.  
  1167. team = "all";
  1168. if ( level.teambased )
  1169. team = getOtherTeam( dog_team );
  1170.  
  1171. if ( !isdefined( enemies ) )
  1172. return false;
  1173.  
  1174. closest = undefined;
  1175. closestDistsq = undefined;
  1176. secondClosest = undefined;
  1177. secondClosestDistsq = undefined;
  1178.  
  1179. for ( i = 0; i < enemies.size; i++ )
  1180. {
  1181. player = node.nearbyPlayers[team][i];
  1182.  
  1183. if ( !isdefined( player ) )
  1184. continue;
  1185. if ( player.sessionstate != "playing" )
  1186. continue;
  1187. if ( player == self )
  1188. continue;
  1189.  
  1190. distsq = distanceSquared( node.origin, player.origin );
  1191. if ( !isdefined( closest ) || distsq < closestDistsq )
  1192. {
  1193. secondClosest = closest;
  1194. secondClosestDistsq = closestDistsq;
  1195.  
  1196. closest = player;
  1197. closestDistSq = distsq;
  1198. }
  1199. else if ( !isdefined( secondClosest ) || distsq < secondClosestDistSq )
  1200. {
  1201. secondClosest = player;
  1202. secondClosestDistSq = distsq;
  1203. }
  1204. }
  1205.  
  1206. if ( isdefined( closest ) )
  1207. {
  1208. if ( bullettracepassed( closest.origin + (0,0,50), node.origin + (0,0,50), false, undefined) )
  1209. return true;
  1210. }
  1211. if ( isdefined( secondClosest ) )
  1212. {
  1213. if ( bullettracepassed( secondClosest.origin + (0,0,50), node.origin + (0,0,50), false, undefined) )
  1214. return true;
  1215. }
  1216.  
  1217. return false;
  1218. }
  1219.  
  1220. update_all_nodes( nodes, team )
  1221. {
  1222. for ( i = 0; i < nodes.size; i++ )
  1223. {
  1224. nodeUpdate( nodes[i], team );
  1225. }
  1226. }
  1227.  
  1228. avoidEnemies(nodes, team,teambased)
  1229. {
  1230. lospenalty = getLosPenalty();
  1231.  
  1232. otherteam = "axis";
  1233. if ( team == "axis" )
  1234. otherteam = "allies";
  1235.  
  1236. minDistTeam = otherteam;
  1237.  
  1238. if ( !teambased )
  1239. {
  1240. minDistTeam = "all";
  1241. }
  1242.  
  1243. avoidWeight = getdvarfloat("scr_spawn_enemyavoidweight");
  1244. if ( avoidWeight != 0 )
  1245. {
  1246. nearbyEnemyOuterRange = getdvarfloat("scr_spawn_enemyavoiddist");
  1247. nearbyEnemyOuterRangeSq = nearbyEnemyOuterRange * nearbyEnemyOuterRange;
  1248. nearbyEnemyPenalty = 1500 * avoidWeight; // typical base weights tend to peak around 1500 or so. this is large enough to upset that while only locally dominating it.
  1249. nearbyEnemyMinorPenalty = 800 * avoidWeight; // additional negative weight for distances up to 2 * nearbyEnemyOuterRange
  1250.  
  1251. lastAttackerOrigin = (-99999,-99999,-99999);
  1252. lastDeathPos = (-99999,-99999,-99999);
  1253.  
  1254. for ( i = 0; i < nodes.size; i++ )
  1255. {
  1256. // penalty for nearby enemies
  1257. mindist = nodes[i].minDist[minDistTeam];
  1258. if ( mindist < nearbyEnemyOuterRange*2 )
  1259. {
  1260. penalty = nearbyEnemyMinorPenalty * (1 - mindist / (nearbyEnemyOuterRange*2));
  1261. if ( mindist < nearbyEnemyOuterRange )
  1262. penalty += nearbyEnemyPenalty * (1 - mindist / nearbyEnemyOuterRange);
  1263. if ( penalty > 0 )
  1264. {
  1265. nodes[i].weight -= penalty;
  1266. }
  1267. }
  1268. }
  1269. }
  1270.  
  1271. // DEBUG
  1272. //prof_end(" spawn_sc");
  1273. }
  1274.  
  1275. nodeUpdate( node, team )
  1276. {
  1277. if ( level.teambased )
  1278. {
  1279. node.sights["axis"] = 0;
  1280. node.sights["allies"] = 0;
  1281.  
  1282. node.nearbyPlayers["axis"] = [];
  1283. node.nearbyPlayers["allies"] = [];
  1284. }
  1285. else
  1286. {
  1287. node.sights = 0;
  1288.  
  1289. node.nearbyPlayers["all"] = [];
  1290. }
  1291.  
  1292. node.nearbyDogs = [];
  1293.  
  1294. nodedir = node.forward;
  1295.  
  1296. debug = false;
  1297.  
  1298. node.distSum["all"] = 0;
  1299. node.distSum["allies"] = 0;
  1300. node.distSum["axis"] = 0;
  1301. node.distSum["dogs"] = 0;
  1302.  
  1303. node.minDist["all"] = 9999999;
  1304. node.minDist["allies"] = 9999999;
  1305. node.minDist["axis"] = 9999999;
  1306. node.minDist["dogs"] = 9999999;
  1307.  
  1308. node.numPlayersAtLastUpdate = 0;
  1309. node.numDogsAtLastUpdate = 0;
  1310.  
  1311. for (i = 0; i < level.players.size; i++)
  1312. {
  1313. player = level.players[i];
  1314.  
  1315. if ( player.sessionstate != "playing" )
  1316. continue;
  1317.  
  1318. diff = player.origin - node.origin;
  1319. diff = (diff[0], diff[1], 0);
  1320. dist = length( diff ); // needs to be actual distance for distSum value
  1321.  
  1322. player_team = "all";
  1323. if ( level.teambased )
  1324. player_team = player.pers["team"];
  1325.  
  1326. if ( dist < 1024 )
  1327. {
  1328. node.nearbyPlayers[player_team][node.nearbyPlayers[player_team].size] = player;
  1329. }
  1330.  
  1331. if ( dist < node.minDist[player_team] )
  1332. node.minDist[player_team] = dist;
  1333.  
  1334. node.distSum[ player_team ] += dist;
  1335. node.numPlayersAtLastUpdate++;
  1336. }
  1337.  
  1338. for (i = 0; i < level.dogs.size; i++)
  1339. {
  1340. dog = level.dogs[i];
  1341.  
  1342. if ( !isdefined(dog) || !isalive(dog) )
  1343. continue;
  1344.  
  1345. diff = dog.origin - node.origin;
  1346. diff = (diff[0], diff[1], 0);
  1347. dist = length( diff ); // needs to be actual distance for distSum value
  1348.  
  1349. if ( dist < 1024 )
  1350. {
  1351. node.nearbyDogs[node.nearbyDogs.size] = dog;
  1352. }
  1353.  
  1354. if ( dist < node.minDist["dogs"] )
  1355. node.minDist["dogs"] = dist;
  1356.  
  1357. node.distSum[ "dogs" ] += dist;
  1358. node.numDogsAtLastUpdate++;
  1359. }
  1360. }
  1361.  
  1362. initWeights(nodes)
  1363. {
  1364. for (i = 0; i < nodes.size; i++)
  1365. nodes[i].weight = 0;
  1366. }
  1367.  
  1368. getAllAlliedAndEnemyPlayers( obj, team )
  1369. {
  1370. if ( level.teambased )
  1371. {
  1372. if ( team == "allies" )
  1373. {
  1374. obj.allies = level.alivePlayers["allies"];
  1375. obj.enemies = level.alivePlayers["axis"];
  1376. }
  1377. else
  1378. {
  1379. assert( team == "axis" );
  1380. obj.allies = level.alivePlayers["axis"];
  1381. obj.enemies = level.alivePlayers["allies"];
  1382. }
  1383. }
  1384. else
  1385. {
  1386. obj.allies = [];
  1387. obj.enemies = level.activePlayers;
  1388. }
  1389. }
  1390.  
  1391. avoidSpawnReuse(nodes)
  1392. {
  1393. time = getTime();
  1394.  
  1395. maxtime = 3*1000;
  1396. maxdistSq = 1024 * 1024;
  1397.  
  1398. for (i = 0; i < nodes.size; i++)
  1399. {
  1400. node = nodes[i];
  1401.  
  1402. if (!isdefined(node.lastspawntime))
  1403. continue;
  1404.  
  1405. timepassed = time - node.lastspawntime;
  1406. if (timepassed < maxtime)
  1407. {
  1408. worsen = 1000 * (1 - timepassed/maxtime);
  1409. node.weight -= worsen;
  1410. }
  1411. }
  1412. }
  1413.  
  1414. flash_dogs( area )
  1415. {
  1416. self endon("disconnect");
  1417.  
  1418. if ( isdefined(level.dogs) )
  1419. {
  1420. for (i = 0; i < level.dogs.size; i++)
  1421. {
  1422. dog = level.dogs[i];
  1423.  
  1424. if ( !isalive(dog) )
  1425. continue;
  1426. if ( dog istouching(area) )
  1427. {
  1428. do_flash = true;
  1429. if ( isPlayer( self ) )
  1430. {
  1431. if ( level.teamBased && (dog.aiteam == self.pers["team"]) )
  1432. {
  1433. do_flash = false;
  1434. }
  1435. else if ( !level.teambased && isdefined(dog.script_owner) && self == dog.script_owner )
  1436. {
  1437. do_flash = false;
  1438. }
  1439. }
  1440.  
  1441. if ( isdefined( dog.lastFlashed ) && dog.lastFlashed + 1500 > gettime() )
  1442. {
  1443. do_flash = false;
  1444. }
  1445.  
  1446. if ( do_flash )
  1447. {
  1448. dog setFlashBanged( true, 500 );
  1449. dog.lastFlashed = gettime();
  1450. }
  1451. }
  1452. }
  1453. }
  1454. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement