mirror of
				https://github.com/ineedbots/iw5_bot_warfare.git
				synced 2025-10-31 04:26:56 +00:00 
			
		
		
		
	Compare commits
	
		
			28 Commits
		
	
	
		
			v2.2.0
			...
			ab7979f9d1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ab7979f9d1 | ||
|  | 3325405f08 | ||
|  | b005f90e99 | ||
|  | 41fb775e97 | ||
|  | 3a68ef5ffc | ||
|  | 7a8041f065 | ||
|  | d92d2c03c4 | ||
|  | 12ca117bdc | ||
|  | 0300692cdd | ||
|  | d2ddce2169 | ||
|  | 7028290495 | ||
|  | 39c6f5054f | ||
|  | b47088538e | ||
|  | 1e0daca087 | ||
|  | dfe2ba0c47 | ||
|  | c8df9ef311 | ||
|  | 0b22a6b8a6 | ||
|  | 60a8f65180 | ||
|  | 5719080f45 | ||
|  | 1bf8314acd | ||
|  | f31a306b0a | ||
|  | c4a222089c | ||
|  | a1651baa5a | ||
|  | 748d261c02 | ||
|  | 06dfea7790 | ||
|  | a9ea7acec3 | ||
|  | 26a5adae13 | ||
|  | a37aadfc2b | 
| @@ -1,10 +1,10 @@ | ||||
| name: main | ||||
| name: gsc-tool | ||||
| 
 | ||||
| on: [push] | ||||
| 
 | ||||
| jobs: | ||||
|   main-win: | ||||
|     name: Test on Windows | ||||
|     name: Compile on Windows | ||||
|     runs-on: windows-latest | ||||
| 
 | ||||
|     steps: | ||||
| @@ -18,4 +18,4 @@ jobs: | ||||
| 
 | ||||
|       - name: Run script | ||||
|         run: | | ||||
|           ci/main.bat | ||||
|           ci/gsc-tool.bat | ||||
							
								
								
									
										16
									
								
								.github/workflows/pregsc.ymloff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/pregsc.ymloff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| name: pregsc | ||||
|  | ||||
| on: [push] | ||||
|  | ||||
| jobs: | ||||
|   main-win: | ||||
|     name: Run on Windows | ||||
|     runs-on: windows-latest | ||||
|  | ||||
|     steps: | ||||
|       - name: Check out files | ||||
|         uses: actions/checkout@main | ||||
|  | ||||
|       - name: Run script | ||||
|         run: | | ||||
|           ci/pregsc.bat | ||||
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +1,14 @@ | ||||
| *.zip | ||||
| *.log | ||||
| *.stat | ||||
| *.exe | ||||
| *.gscbin | ||||
| !ci/ | ||||
| out/ | ||||
| logs/ | ||||
| demos/ | ||||
| missingasset.csv | ||||
| *.exe | ||||
| compiled/ | ||||
| source/ | ||||
| pregsc/ | ||||
| pregsc.dat | ||||
|   | ||||
							
								
								
									
										26
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								README.md
									
									
									
									
									
								
							| @@ -75,19 +75,20 @@ You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfar | ||||
| | bots_main_GUIDs                  | A comma separated list of GUIDs of players who will be given host.                          |               | | ||||
| | bots_main_waitForHostTime        | How many seconds to wait for the host player to connect before adding bots to the match.    | 10            | | ||||
| | bots_main_menu                   | Enable the in-game menu for hosts.                                                          | 1             | | ||||
| | bots_main_debug                  | Enable the in-game waypoint editor.                                                         | 0             | | ||||
| | bots_main_debug                  | Enable the in-game waypoint editor at start of the game, or enable bot event prints. <ul><li>`0` - disable</li><li>`1` - for just debug events</li><li>`2` - for every event</li><ul> | 0 | | ||||
| | bots_main_kickBotsAtEnd          | Kick the bots at the end of a match.                                                        | 0             | | ||||
| | bots_main_chat                   | The rate bots will chat at, set to 0 to disable.                                            | 1.0           | | ||||
| | bots_manage_add                  | Amount of bots to add to the game, once bots are added, resets back to `0`.                 | 0             | | ||||
| | bots_manage_fill                 | Amount of players/bots (look at `bots_manage_fill_mode`) to maintain in the match.          | 0             | | ||||
| | bots_manage_fill_mode            | `bots_manage_fill` players/bots counting method.<ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots.</li></ul> | 0 | | ||||
| | bots_manage_fill_kick            | If the amount of players/bots in the match exceeds `bots_manage_fill`, kick bots until no longer exceeds. | 0     | | ||||
| | bots_manage_fill_mode            | `bots_manage_fill` players/bots counting method.<ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots.</li><li>`2` - exactly `0` but auto adjusts `bots_manage_fill` to map.</li><li>`3` - exactly `1` but auto adjusts `bots_manage_fill` to map.</li><li>`4` - bots are used for balancing teams.</li><li>`5` - exactly `4` but auto adjusts `bots_manage_fill` to map.</li></ul> | 0 | | ||||
| | bots_manage_fill_watchplayers    | Bots will not be added until one player is in the game                                      | 0             | | ||||
| | bots_manage_fill_kick            | If the amount of players/bots in the match exceeds `bots_manage_fill`, kick bots until no longer exceeds. | 0 | | ||||
| | bots_manage_fill_spec            | If when counting players for `bots_manage_fill` should include spectators.                  | 1             | | ||||
| | bots_team                        | One of `autoassign`, `allies`, `axis`, `spectator`, or `custom`. What team the bots should be on. | autoassign | | ||||
| | bots_team_amount                 | When `bots_team` is set to `custom`. The amount of bots to be placed on the axis team. The remainder will be placed on the allies team. | 0 | | ||||
| | bots_team_force                  | If the server should force bots' teams according to the `bots_team` value. When `bots_team` is `autoassign`, unbalanced teams will be balanced. This dvar is ignored when `bots_team` is `custom`. | 0     | | ||||
| | bots_team_mode                   | When `bots_team_force` is `true` and `bots_team` is `autoassign`, players/bots counting method. <ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots</li></ul> | 0 | | ||||
| | bots_skill                       | Bots' difficulty.<ul><li>`0` - Random difficulty for each bot.</li><li>`1` - Easiest difficulty for all bots.</li><li>`2` to `6` - Between easy and hard difficulty for all bots.</li><li>`7` - The hardest difficulty for all bots.</li><li>`8` - custom (look at the `bots_skill_<team>_<difficulty>` dvars</li></ul> | 0 | | ||||
| | bots_team_force                  | If the server should force bots' teams according to the `bots_team` value. When `bots_team` is `autoassign`, unbalanced teams will be balanced. This dvar is ignored when `bots_team` is `custom`. | 0 | | ||||
| | bots_team_mode                   | When `bots_team_force` is `1` and `bots_team` is `autoassign`, players/bots counting method. <ul><li>`0` - counts both players and bots.</li><li>`1` - only counts bots</li></ul> | 0 | | ||||
| | bots_skill                       | Bots' difficulty.<ul><li>`0` - Random difficulty for each bot.</li><li>`1` - Easiest difficulty for all bots.</li><li>`2` to `6` - Between easy and hard difficulty for all bots.</li><li>`7` - The hardest difficulty for all bots.</li><li>`8` - custom (look at the `bots_skill_<team>_<difficulty>` dvars)</li><li>`9` - Every difficulty parameter is randomized</li></ul> | 0 | | ||||
| | bots_skill_axis_hard             | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the axis team. | 0            | | ||||
| | bots_skill_axis_med              | When `bots_skill` is set to `8`, the amount of medium difficulty bots to set on the axis team. The remaining bots on the team will be set to easy difficulty. | 0 | | ||||
| | bots_skill_allies_hard           | When `bots_skill` is set to `8`, the amount of hard difficulty bots to set on the allies team. | 0          | | ||||
| @@ -112,10 +113,18 @@ You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfar | ||||
| | bots_play_aim                    | If the bots can aim.                                                                           | 1          | | ||||
|  | ||||
| ## Changelog | ||||
| - v2.3.0 | ||||
|   - Fixed bots aiming in ac130/chopper being broken at times | ||||
|   - Bots properly use pred missiles | ||||
|   - Smoothed bot aim at range | ||||
|   - Fixed bots_manage_fill_spec players being counted with bots_manage_fill_mode 1 (bot only) | ||||
|   - Added bots_manage_fill_watchplayers dvar | ||||
|   - Bots hop off turrets if they get stuck on one | ||||
|   - Fixed script variable leak with opening and closing the in-game menu | ||||
|  | ||||
| - v2.2.0 | ||||
|   - Bots can now melee lunge | ||||
|   - Fixed some chat related script runtime errors | ||||
|   - Waypoints only load from csv now | ||||
|   - Fix bots possibly being stuck in sab | ||||
|   - Major cleanup | ||||
|  | ||||
| @@ -128,9 +137,10 @@ You can find the ModDB release post [here](https://www.moddb.com/mods/bot-warfar | ||||
| - INeedGames - http://www.moddb.com/mods/bot-warfare | ||||
| - tinkie101 - https://web.archive.org/web/20120326060712/http://alteriw.net/viewtopic.php?f=72&t=4869 | ||||
| - PeZBot team - http://www.moddb.com/mods/pezbot | ||||
| - apdonato - http://rsebots.blogspot.ca/ | ||||
| - apdonato - https://web.archive.org/web/20240516065610/http://rsebots.blogspot.com/ | ||||
| - Ability | ||||
| - Salvation | ||||
| - Xensik - https://github.com/xensik/gsc-tool | ||||
|  | ||||
| ### Waypoint Creators | ||||
| - FragsAreUs - https://github.com/FragsAreUs | ||||
|   | ||||
							
								
								
									
										6
									
								
								ci/gsc-tool.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ci/gsc-tool.bat
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| @echo off | ||||
|  | ||||
| xcopy /y .\ci\*.gscbin .\ | ||||
| rm .\scripts\mp\bots_adapter_piw5.gsc | ||||
|  | ||||
| gsc-tool.exe -m comp -g iw5 -s pc .\ | ||||
| @@ -1,6 +0,0 @@ | ||||
| @echo off | ||||
|  | ||||
| xcopy /y ci . | ||||
| rm scripts\mp\bots_adapter_piw5.gsc | ||||
|  | ||||
| gsc-tool.exe -m comp -g iw5 -s pc . | ||||
							
								
								
									
										10
									
								
								ci/pregsc.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								ci/pregsc.bat
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| @echo off | ||||
|  | ||||
| if not exist ".\source\" mkdir .\source\ | ||||
| if not exist ".\source\scripts\" mkdir .\source\scripts\ | ||||
| if not exist ".\source\maps\" mkdir .\source\maps\ | ||||
|  | ||||
| xcopy /y /s /e .\scripts\ .\source\scripts\ | ||||
| xcopy /y /s /e .\maps\ .\source\maps\ | ||||
|  | ||||
| preGSC.exe -noforeach -nopause -infold .\source\ -outfold .\pregsc\ | ||||
| @@ -15,7 +15,7 @@ | ||||
| */ | ||||
| init() | ||||
| { | ||||
| 	level.bw_version = "2.2.0"; | ||||
| 	level.bw_version = "2.3.0"; | ||||
| 	 | ||||
| 	if ( getdvar( "bots_main" ) == "" ) | ||||
| 	{ | ||||
| @@ -80,6 +80,11 @@ init() | ||||
| 		setdvar( "bots_manage_fill_kick", false ); // kick bots if too many | ||||
| 	} | ||||
| 	 | ||||
| 	if ( getdvar( "bots_manage_fill_watchplayers" ) == "" ) | ||||
| 	{ | ||||
| 		setdvar( "bots_manage_fill_watchplayers", false ); // add bots when player exists, kick if not | ||||
| 	} | ||||
| 	 | ||||
| 	if ( getdvar( "bots_team" ) == "" ) | ||||
| 	{ | ||||
| 		setdvar( "bots_team", "autoassign" ); // which team for bots to join | ||||
| @@ -218,8 +223,11 @@ init() | ||||
| 	if ( !isdefined( game[ "botWarfare" ] ) ) | ||||
| 	{ | ||||
| 		game[ "botWarfare" ] = true; | ||||
| 		game[ "botWarfareInitTime" ] = gettime(); | ||||
| 	} | ||||
| 	 | ||||
| 	level.bot_inittime = gettime(); | ||||
| 	 | ||||
| 	level.defuseobject = undefined; | ||||
| 	level.bots_smokelist = List(); | ||||
| 	level.bots_fraglist = List(); | ||||
| @@ -277,6 +285,7 @@ init() | ||||
| 	level.bots_fullautoguns[ "remote" ] = true; | ||||
| 	 | ||||
| 	level thread fixGamemodes(); | ||||
| 	level thread fixPredMissile(); | ||||
| 	 | ||||
| 	level thread onPlayerConnect(); | ||||
| 	level thread addNotifyOnAirdrops(); | ||||
| @@ -285,6 +294,26 @@ init() | ||||
| 	level thread auditModels(); | ||||
| 	 | ||||
| 	level thread handleBots(); | ||||
| 	level thread onPlayerChat(); | ||||
| 	 | ||||
| 	array_thread( getentarray( "misc_turret", "classname" ), ::turret_monitoruse_watcher ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Change func pointer to ours, so that we can link the player ref to the rocket | ||||
| */ | ||||
| fixPredMissile() | ||||
| { | ||||
| 	for ( i = 0; i < 19; i++ ) | ||||
| 	{ | ||||
| 		if ( isdefined( level.killstreakfuncs ) && isdefined( level.killstreakfuncs[ "predator_missile" ] ) ) | ||||
| 		{ | ||||
| 			level.killstreakfuncs[ "predator_missile" ] = ::tryUsePredatorMissileFix; | ||||
| 			break; | ||||
| 		} | ||||
| 		 | ||||
| 		wait 0.05; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -847,6 +876,23 @@ onPlayerConnect() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	When a bot disconnects. | ||||
| */ | ||||
| onDisconnectPlayer() | ||||
| { | ||||
| 	name = self.name; | ||||
| 	 | ||||
| 	self waittill( "disconnect" ); | ||||
| 	waittillframeend; | ||||
| 	 | ||||
| 	for ( i = 0; i < level.bots.size; i++ ) | ||||
| 	{ | ||||
| 		bot = level.bots[ i ]; | ||||
| 		bot BotNotifyBotEvent( "connection", "disconnected", self, name ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	When a bot disconnects. | ||||
| */ | ||||
| @@ -864,6 +910,14 @@ connected() | ||||
| { | ||||
| 	self endon( "disconnect" ); | ||||
| 	 | ||||
| 	for ( i = 0; i < level.bots.size; i++ ) | ||||
| 	{ | ||||
| 		bot = level.bots[ i ]; | ||||
| 		bot BotNotifyBotEvent( "connection", "connected", self, self.name ); | ||||
| 	} | ||||
| 	 | ||||
| 	self thread onDisconnectPlayer(); | ||||
| 	 | ||||
| 	if ( !isdefined( self.pers[ "bot_host" ] ) ) | ||||
| 	{ | ||||
| 		self thread doHostCheck(); | ||||
| @@ -1294,7 +1348,7 @@ addBots_loop() | ||||
| 	 | ||||
| 	fillMode = getdvarint( "bots_manage_fill_mode" ); | ||||
| 	 | ||||
| 	if ( fillMode == 2 || fillMode == 3 ) | ||||
| 	if ( fillMode == 2 || fillMode == 3 || fillMode == 5 ) | ||||
| 	{ | ||||
| 		setdvar( "bots_manage_fill", getGoodMapAmount() ); | ||||
| 	} | ||||
| @@ -1304,6 +1358,8 @@ addBots_loop() | ||||
| 	players = 0; | ||||
| 	bots = 0; | ||||
| 	spec = 0; | ||||
| 	axisplayers = 0; | ||||
| 	alliesplayers = 0; | ||||
| 	 | ||||
| 	playercount = level.players.size; | ||||
| 	 | ||||
| @@ -1322,37 +1378,6 @@ addBots_loop() | ||||
| 		else | ||||
| 		{ | ||||
| 			players++; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	if ( !randomint( 999 ) ) | ||||
| 	{ | ||||
| 		setdvar( "testclients_doreload", true ); | ||||
| 		wait 0.1; | ||||
| 		setdvar( "testclients_doreload", false ); | ||||
| 		doExtraCheck(); | ||||
| 	} | ||||
| 	 | ||||
| 	if ( fillMode == 4 ) | ||||
| 	{ | ||||
| 		axisplayers = 0; | ||||
| 		alliesplayers = 0; | ||||
| 		 | ||||
| 		playercount = level.players.size; | ||||
| 		 | ||||
| 		for ( i = 0; i < playercount; i++ ) | ||||
| 		{ | ||||
| 			player = level.players[ i ]; | ||||
| 			 | ||||
| 			if ( player is_bot() ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( !isdefined( player.pers[ "team" ] ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( player.pers[ "team" ] == "axis" ) | ||||
| 			{ | ||||
| @@ -1363,26 +1388,19 @@ addBots_loop() | ||||
| 				alliesplayers++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 		result = fillAmount - abs( axisplayers - alliesplayers ) + bots; | ||||
| 	if ( getdvarint( "bots_manage_fill_spec" ) ) | ||||
| 	{ | ||||
| 		players += spec; | ||||
| 	} | ||||
| 	 | ||||
| 		if ( players == 0 ) | ||||
| 		{ | ||||
| 			if ( bots < fillAmount ) | ||||
| 			{ | ||||
| 				result = fillAmount - 1; | ||||
| 			} | ||||
| 			else if ( bots > fillAmount ) | ||||
| 			{ | ||||
| 				result = fillAmount + 1; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				result = fillAmount; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		bots = result; | ||||
| 	if ( !randomint( 999 ) ) | ||||
| 	{ | ||||
| 		setdvar( "testclients_doreload", true ); | ||||
| 		wait 0.1; | ||||
| 		setdvar( "testclients_doreload", false ); | ||||
| 		doExtraCheck(); | ||||
| 	} | ||||
| 	 | ||||
| 	amount = bots; | ||||
| @@ -1392,22 +1410,46 @@ addBots_loop() | ||||
| 		amount += players; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( getdvarint( "bots_manage_fill_spec" ) ) | ||||
| 	// use bots as balance | ||||
| 	if ( fillMode == 4 || fillMode == 5 ) | ||||
| 	{ | ||||
| 		amount += spec; | ||||
| 		diffPlayers = abs( alliesplayers - axisplayers ); | ||||
| 		amount = fillAmount - ( diffPlayers - bots ); | ||||
| 		 | ||||
| 		if ( players + diffPlayers < fillAmount ) | ||||
| 		{ | ||||
| 			amount = players + bots; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	if ( players <= 0 && getdvarint( "bots_manage_fill_watchplayers" ) ) | ||||
| 	{ | ||||
| 		amount = fillAmount + bots; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( amount < fillAmount ) | ||||
| 	{ | ||||
| 		setdvar( "bots_manage_add", 1 ); | ||||
| 		setdvar( "bots_manage_add", fillAmount - amount ); | ||||
| 	} | ||||
| 	else if ( amount > fillAmount && getdvarint( "bots_manage_fill_kick" ) ) | ||||
| 	{ | ||||
| 		tempBot = getBotToKick(); | ||||
| 		botsToKick = amount - fillAmount; | ||||
| 		 | ||||
| 		if ( isdefined( tempBot ) ) | ||||
| 		if ( botsToKick > 64 ) | ||||
| 		{ | ||||
| 			kick( tempBot getentitynumber() ); | ||||
| 			botsToKick = 64; | ||||
| 		} | ||||
| 		 | ||||
| 		for ( i = 0; i < botsToKick; i++ ) | ||||
| 		{ | ||||
| 			tempBot = getBotToKick(); | ||||
| 			 | ||||
| 			if ( isdefined( tempBot ) ) | ||||
| 			{ | ||||
| 				kick( tempBot getentitynumber(), "EXE_PLAYERKICKED" ); | ||||
| 				 | ||||
| 				wait 0.25; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1552,3 +1594,57 @@ doFiringThread() | ||||
| 	wait 1; | ||||
| 	self.bots_firing = false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	When a player chats | ||||
| */ | ||||
| onPlayerChat() | ||||
| { | ||||
| 	for ( ;; ) | ||||
| 	{ | ||||
| 		level waittill( "say", message, player, is_hidden ); | ||||
| 		 | ||||
| 		for ( i = 0; i < level.bots.size; i++ ) | ||||
| 		{ | ||||
| 			bot = level.bots[ i ]; | ||||
| 			 | ||||
| 			bot BotNotifyBotEvent( "chat", "chat", message, player, is_hidden ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Monitors turret usage | ||||
| */ | ||||
| turret_monitoruse_watcher() | ||||
| { | ||||
| 	self endon( "death" ); | ||||
| 	 | ||||
| 	for ( ;; ) | ||||
| 	{ | ||||
| 		self waittill ( "trigger", player ); | ||||
| 		 | ||||
| 		self monitor_player_turret( player ); | ||||
| 		 | ||||
| 		self.owner = undefined; | ||||
| 		 | ||||
| 		if ( isdefined( player ) ) | ||||
| 		{ | ||||
| 			player.turret = undefined; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	While player uses turret | ||||
| */ | ||||
| monitor_player_turret( player ) | ||||
| { | ||||
| 	player endon( "death" ); | ||||
| 	player endon( "disconnect" ); | ||||
| 	 | ||||
| 	player.turret = self; | ||||
| 	self.owner = player; | ||||
| 	 | ||||
| 	self waittill( "turret_deactivate" ); | ||||
| } | ||||
|   | ||||
| @@ -328,10 +328,43 @@ start_chat_watch() | ||||
| 			case "box_cap": | ||||
| 				self thread bot_chat_box_cap_watch( a, b, c, d, e, f, g ); | ||||
| 				break; | ||||
| 				 | ||||
| 			case "connection": | ||||
| 				self thread bot_chat_connection_player_watch( a, b, c, d, e, f, g ); | ||||
| 				break; | ||||
| 				 | ||||
| 			case "chat": | ||||
| 				self thread bot_chat_chat_player_watch( a, b, c, d, e, f, g ); | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	When another player chats | ||||
| */ | ||||
| bot_chat_chat_player_watch( chatstr, message, player, is_hidden, e, f, g ) | ||||
| { | ||||
| 	self endon( "disconnect" ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	When a player connected | ||||
| */ | ||||
| bot_chat_connection_player_watch( conn, player, playername, d, e, f, g ) | ||||
| { | ||||
| 	self endon( "disconnect" ); | ||||
| 	 | ||||
| 	switch ( conn ) | ||||
| 	{ | ||||
| 		case "connected": | ||||
| 			break; | ||||
| 			 | ||||
| 		case "disconnected": | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	start_startgame_watch | ||||
| */ | ||||
|   | ||||
| @@ -375,11 +375,208 @@ watchUsingRemote() | ||||
| 			self watchUsingTurret(); | ||||
| 		} | ||||
| 		 | ||||
| 		if ( isdefined( self.rocket ) ) | ||||
| 		{ | ||||
| 			self watchUsingPred(); | ||||
| 			self BotBuiltinBotAction( "-remote" ); | ||||
| 		} | ||||
| 		 | ||||
| 		self.bot.targets = []; | ||||
| 		self notify( "kill_goal" ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Returns the angle delta | ||||
| */ | ||||
| getRemoteAngleSpeed( len ) | ||||
| { | ||||
| 	furthest = 10.0; | ||||
| 	max_speed = 127; | ||||
| 	 | ||||
| 	switch ( self.pers[ "bots" ][ "skill" ][ "base" ] ) | ||||
| 	{ | ||||
| 		case 1: | ||||
| 			furthest = 5.0; | ||||
| 			max_speed = 20; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 2: | ||||
| 			furthest = 6.0; | ||||
| 			max_speed = 35; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 3: | ||||
| 			furthest = 7.0; | ||||
| 			max_speed = 55; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 4: | ||||
| 			furthest = 8.0; | ||||
| 			max_speed = 65; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 5: | ||||
| 			furthest = 9.0; | ||||
| 			max_speed = 75; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 6: | ||||
| 			furthest = 10.0; | ||||
| 			max_speed = 100; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 7: | ||||
| 			furthest = 15.0; | ||||
| 			max_speed = 127; | ||||
| 			break; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( len >= furthest ) | ||||
| 	{ | ||||
| 		return max_speed; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( len <= 0.0 ) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	 | ||||
| 	return Round( ( len / furthest ) * max_speed ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	time to boost the rocket | ||||
| */ | ||||
| getRemoteBoostTime() | ||||
| { | ||||
| 	switch ( self.pers[ "bots" ][ "skill" ][ "base" ] ) | ||||
| 	{ | ||||
| 		case 1: | ||||
| 			return 99999; | ||||
| 			 | ||||
| 		case 2: | ||||
| 			return 15000; | ||||
| 			 | ||||
| 		case 3: | ||||
| 			return 10000; | ||||
| 			 | ||||
| 		case 4: | ||||
| 			return 5000; | ||||
| 			 | ||||
| 		case 5: | ||||
| 			return 2500; | ||||
| 			 | ||||
| 		case 6: | ||||
| 			return 1000; | ||||
| 			 | ||||
| 		case 7: | ||||
| 			return 500; | ||||
| 			 | ||||
| 		default: | ||||
| 			return 500; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	While in rocket | ||||
| */ | ||||
| watchUsingPred() | ||||
| { | ||||
| 	self.rocket endon( "death" ); | ||||
| 	 | ||||
| 	self BotBuiltinBotRemoteAngles( 0, 0 ); | ||||
| 	self BotBuiltinBotAction( "+remote" ); | ||||
| 	 | ||||
| 	pressedFire = false; | ||||
| 	sTime = gettime(); | ||||
| 	 | ||||
| 	while ( isdefined( self.rocket ) ) | ||||
| 	{ | ||||
| 		self.bot.targets = []; // dont want to fire from aim thread | ||||
| 		// because geteye doesnt return the eye of the missile | ||||
| 		 | ||||
| 		target = undefined; | ||||
| 		myeye = self.rocket.origin; | ||||
| 		myangles = self.rocket.angles; | ||||
| 		bestfov = 0.0; | ||||
| 		 | ||||
| 		for ( i = level.players.size - 1; i >= 0; i-- ) | ||||
| 		{ | ||||
| 			player = level.players[ i ]; | ||||
| 			 | ||||
| 			if ( !isdefined( player ) || !isdefined( player.team ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( player == self || ( level.teambased && player.team == self.team ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( player.sessionstate != "playing" || !isreallyalive( player ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( player _hasperk( "specialty_blindeye" ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( !bullettracepassed( myeye, player.origin + ( 0, 0, 25 ), false, self.rocket ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			thisfov = getConeDot( player.origin, myeye, myangles ); | ||||
| 			 | ||||
| 			if ( thisfov < 0.75 ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			if ( isdefined( target ) && thisfov < bestfov ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			target = player; | ||||
| 			bestfov = thisfov; | ||||
| 		} | ||||
| 		 | ||||
| 		if ( isdefined( target ) ) | ||||
| 		{ | ||||
| 			if ( !pressedFire && gettime() - sTime > self getRemoteBoostTime() ) | ||||
| 			{ | ||||
| 				pressedFire = true; | ||||
| 				self thread pressFire(); | ||||
| 			} | ||||
| 			 | ||||
| 			if ( bestfov < 0.999995 && distancesquared( target.origin, myeye ) > 256 * 256 ) | ||||
| 			{ | ||||
| 				angles = vectortoangles( ( target.origin - myeye ) - anglestoforward( myangles ) ); | ||||
| 				angles -= myangles; | ||||
| 				angles = ( angleclamp180( angles[ 0 ] ), angleclamp180( angles[ 1 ] ), 0 ); | ||||
| 				angles = vectornormalize( angles ) * self getRemoteAngleSpeed( length( angles ) ); | ||||
| 				 | ||||
| 				self BotBuiltinBotRemoteAngles( int( angles[ 0 ] ), int( angles[ 1 ] ) ); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				self BotBuiltinBotRemoteAngles( 0, 0 ); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			self BotBuiltinBotRemoteAngles( 0, 0 ); | ||||
| 		} | ||||
| 		 | ||||
| 		wait 0.05; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	watchUsingTurret | ||||
| */ | ||||
| @@ -646,6 +843,13 @@ watchPickupGun() | ||||
| 			continue; | ||||
| 		} | ||||
| 		 | ||||
| 		// todo have bots use turrets instead of just kicking them off of it | ||||
| 		if ( isdefined( self.turret ) ) | ||||
| 		{ | ||||
| 			self thread use( 0.5 ); | ||||
| 			continue; | ||||
| 		} | ||||
| 		 | ||||
| 		weap = self getcurrentweapon(); | ||||
| 		 | ||||
| 		if ( weap != "none" && self getammocount( weap ) ) | ||||
| @@ -1177,24 +1381,27 @@ updateBones() | ||||
| 	self endon( "disconnect" ); | ||||
| 	self endon( "spawned_player" ); | ||||
| 	 | ||||
| 	bones = strtok( self.pers[ "bots" ][ "skill" ][ "bones" ], "," ); | ||||
| 	waittime = self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ]; | ||||
| 	 | ||||
| 	for ( ;; ) | ||||
| 	{ | ||||
| 		self waittill_any_timeout( waittime, "new_enemy" ); | ||||
| 		oldbones = self.pers[ "bots" ][ "skill" ][ "bones" ]; | ||||
| 		bones = strtok( oldbones, "," ); | ||||
| 		 | ||||
| 		if ( !isalive( self ) ) | ||||
| 		while ( oldbones == self.pers[ "bots" ][ "skill" ][ "bones" ] ) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 			self waittill_any_timeout( self.pers[ "bots" ][ "skill" ][ "bone_update_interval" ], "new_enemy" ); | ||||
| 			 | ||||
| 		if ( !isdefined( self.bot.target ) ) | ||||
| 		{ | ||||
| 			continue; | ||||
| 		} | ||||
| 			if ( !isalive( self ) ) | ||||
| 			{ | ||||
| 				return; | ||||
| 			} | ||||
| 			 | ||||
| 		self.bot.target.bone = random( bones ); | ||||
| 			if ( !isdefined( self.bot.target ) ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			self.bot.target.bone = random( bones ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1303,6 +1510,23 @@ targetObjUpdateNoTrace( obj ) | ||||
| 	obj.didlook = false; | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Returns true if myEye can see the bone of self | ||||
| */ | ||||
| checkTraceForBone( myEye, bone ) | ||||
| { | ||||
| 	boneLoc = self gettagorigin( bone ); | ||||
| 	 | ||||
| 	if ( !isdefined( boneLoc ) ) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	trace = bullettrace( myEye, boneLoc, false, undefined ); | ||||
| 	 | ||||
| 	return ( sighttracepassed( myEye, boneLoc, false, undefined ) && ( trace[ "fraction" ] >= 1.0 || trace[ "surfacetype" ] == "glass" ) ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	The main target thread, will update the bot's main target. Will auto target enemy players and handle script targets. | ||||
| */ | ||||
| @@ -1447,21 +1671,9 @@ target_loop() | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				targetHead = player gettagorigin( "j_head" ); | ||||
| 				targetAnkleLeft = player gettagorigin( "j_ankle_le" ); | ||||
| 				targetAnkleRight = player gettagorigin( "j_ankle_ri" ); | ||||
| 				 | ||||
| 				traceHead = bullettrace( myEye, targetHead, false, undefined ); | ||||
| 				traceAnkleLeft = bullettrace( myEye, targetAnkleLeft, false, undefined ); | ||||
| 				traceAnkleRight = bullettrace( myEye, targetAnkleRight, false, undefined ); | ||||
| 				 | ||||
| 				canTargetPlayer = ( ( sighttracepassed( myEye, targetHead, false, undefined ) || | ||||
| 							sighttracepassed( myEye, targetAnkleLeft, false, undefined ) || | ||||
| 							sighttracepassed( myEye, targetAnkleRight, false, undefined ) ) | ||||
| 							 | ||||
| 						&& ( ( traceHead[ "fraction" ] >= 1.0 || traceHead[ "surfacetype" ] == "glass" ) || | ||||
| 							( traceAnkleLeft[ "fraction" ] >= 1.0 || traceAnkleLeft[ "surfacetype" ] == "glass" ) || | ||||
| 							( traceAnkleRight[ "fraction" ] >= 1.0 || traceAnkleRight[ "surfacetype" ] == "glass" ) ) | ||||
| 				canTargetPlayer = ( ( player checkTraceForBone( myEye, "j_head" ) || | ||||
| 							player checkTraceForBone( myEye, "j_ankle_le" ) || | ||||
| 							player checkTraceForBone( myEye, "j_ankle_ri" ) ) | ||||
| 							 | ||||
| 						&& ( ignoreSmoke || | ||||
| 							SmokeTrace( myEye, player.origin, level.smokeradius ) || | ||||
| @@ -1937,7 +2149,7 @@ aim_loop() | ||||
| 					{ | ||||
| 						self thread bot_lookat( target gettagorigin( "j_spine4" ), 0.05 ); | ||||
| 					} | ||||
| 					else if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 ) | ||||
| 					else if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) | ||||
| 					{ | ||||
| 						self thread bot_lookat( aimpos, 0.05 ); | ||||
| 					} | ||||
| @@ -1955,7 +2167,7 @@ aim_loop() | ||||
| 					 | ||||
| 					conedot = getConeDot( aimpos, eyePos, angles ); | ||||
| 					 | ||||
| 					if ( !nadeAimOffset && conedot > 0.999 && lengthsquared( aimoffset ) < 0.05 ) | ||||
| 					if ( !nadeAimOffset && conedot > 0.999995 && lengthsquared( aimoffset ) < 0.05 ) | ||||
| 					{ | ||||
| 						self thread bot_lookat( aimpos, 0.05 ); | ||||
| 					} | ||||
| @@ -2137,6 +2349,7 @@ aim() | ||||
| 	for ( ;; ) | ||||
| 	{ | ||||
| 		wait 0.05; | ||||
| 		waittillframeend; | ||||
| 		 | ||||
| 		if ( !isalive( self ) ) | ||||
| 		{ | ||||
| @@ -2372,9 +2585,9 @@ walk_loop() | ||||
| 	 | ||||
| 	dist = 16; | ||||
| 	 | ||||
| 	if ( level.waypointcount ) | ||||
| 	if ( level.waypoints.size ) | ||||
| 	{ | ||||
| 		goal = level.waypoints[ randomint( level.waypointcount ) ].origin; | ||||
| 		goal = level.waypoints[ randomint( level.waypoints.size ) ].origin; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -3350,7 +3563,7 @@ bot_lookat( pos, time, vel, doAimPredict ) | ||||
| 	for ( i = 0; i < steps; i++ ) | ||||
| 	{ | ||||
| 		myAngle = ( angleclamp180( myAngle[ 0 ] + X ), angleclamp180( myAngle[ 1 ] + Y ), 0 ); | ||||
| 		self setplayerangles( myAngle ); | ||||
| 		self BotBuiltinBotAngles( myAngle ); | ||||
| 		wait 0.05; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -5628,27 +5628,6 @@ getKillstreakTargetLocation() | ||||
| 	return location; | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Clears remote usage when bot dies | ||||
| */ | ||||
| clear_remote_on_death( isac130 ) | ||||
| { | ||||
| 	self endon( "bot_clear_remote_on_death" ); | ||||
| 	level endon( "game_ended" ); | ||||
| 	 | ||||
| 	self waittill_either( "death", "disconnect" ); | ||||
| 	 | ||||
| 	if ( isdefined( isac130 ) && isac130 ) | ||||
| 	{ | ||||
| 		level.ac130inuse = false; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( isdefined( self ) ) | ||||
| 	{ | ||||
| 		self clearusingremote(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Bots think to use killstreaks | ||||
| */ | ||||
| @@ -5706,6 +5685,11 @@ bot_killstreak_think_loop( data ) | ||||
| 		self thread BotPressAttack( 0.05 ); | ||||
| 	} | ||||
| 	 | ||||
| 	if ( iskillstreakweapon( curWeap ) ) | ||||
| 	{ | ||||
| 		self thread changeToWeapon( self getlastweapon() ); | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	useableStreaks = []; | ||||
| 	 | ||||
| @@ -5898,49 +5882,11 @@ bot_killstreak_think_loop( data ) | ||||
| 			self BotNotifyBotEvent( "killstreak", "call", streakName, location ); | ||||
| 			 | ||||
| 			self BotRandomStance(); | ||||
| 			self setusingremote( "remotemissile" ); | ||||
| 			self thread clear_remote_on_death(); | ||||
| 			self BotStopMoving( true ); | ||||
| 			self changeToWeapon( ksWeap ); | ||||
| 			 | ||||
| 			if ( !self changeToWeapon( ksWeap ) ) | ||||
| 			{ | ||||
| 				self clearusingremote(); | ||||
| 				self notify( "bot_clear_remote_on_death" ); | ||||
| 				self BotStopMoving( false ); | ||||
| 				return; | ||||
| 			} | ||||
| 			 | ||||
| 			wait 0.05; | ||||
| 			self thread changeToWeapon( ksWeap ); // prevent script from changing back | ||||
| 			 | ||||
| 			wait 1; | ||||
| 			self notify( "bot_clear_remote_on_death" ); | ||||
| 			wait 3; | ||||
| 			self BotStopMoving( false ); | ||||
| 			 | ||||
| 			if ( self isemped() || self isnuked() ) | ||||
| 			{ | ||||
| 				self clearusingremote(); | ||||
| 				self thread changeToWeapon( curWeap ); | ||||
| 				return; | ||||
| 			} | ||||
| 			 | ||||
| 			self BotFreezeControls( true ); | ||||
| 			 | ||||
| 			self thread maps\mp\killstreaks\_killstreaks::updatekillstreaks(); | ||||
| 			self maps\mp\killstreaks\_killstreaks::usedkillstreak( streakName, true ); | ||||
| 			 | ||||
| 			rocket = magicbullet( "remotemissile_projectile_mp", self.origin + ( 0.0, 0.0, 7000.0 - ( self.pers[ "bots" ][ "skill" ][ "base" ] * 400 ) ), location, self ); | ||||
| 			rocket.lifeid = lifeId; | ||||
| 			rocket.type = "remote"; | ||||
| 			 | ||||
| 			rocket thread maps\mp\gametypes\_weapons::addmissiletosighttraces( self.pers[ "team" ] ); | ||||
| 			rocket thread maps\mp\killstreaks\_remotemissile::handledamage(); | ||||
| 			thread maps\mp\killstreaks\_remotemissile::missileeyes( self, rocket ); | ||||
| 			 | ||||
| 			self waittill( "stopped_using_remote" ); | ||||
| 			 | ||||
| 			wait 1; | ||||
| 			self BotFreezeControls( false ); | ||||
| 		} | ||||
| 		else if ( streakName == "ac130" || streakName == "remote_mortar" || streakName == "osprey_gunner" ) | ||||
| 		{ | ||||
|   | ||||
| @@ -129,6 +129,28 @@ BotBuiltinBotMeleeParams( entNum, dist ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Sets remote angles | ||||
| */ | ||||
| BotBuiltinBotRemoteAngles( pitch, yaw ) | ||||
| { | ||||
| 	if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botremoteangles" ] ) ) | ||||
| 	{ | ||||
| 		self [[ level.bot_builtins[ "botremoteangles" ] ]]( pitch, yaw ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Sets angles | ||||
| */ | ||||
| BotBuiltinBotAngles( angles ) | ||||
| { | ||||
| 	if ( isdefined( level.bot_builtins ) && isdefined( level.bot_builtins[ "botangles" ] ) ) | ||||
| 	{ | ||||
| 		self [[ level.bot_builtins[ "botangles" ] ]]( angles ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Returns if player is the host | ||||
| */ | ||||
| @@ -356,12 +378,22 @@ BotStopMoving( what ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Waits till frame end so that if two notifies happen in the same frame, the other will not be missed. | ||||
| */ | ||||
| BotNotifyBotEvent_( msg, a, b, c, d, e, f, g ) | ||||
| { | ||||
| 	self endon( "disconnect" ); | ||||
| 	waittillframeend; // wait for the waittills to setup again | ||||
| 	self notify( "bot_event", msg, a, b, c, d, e, f, g ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Notify the bot chat message | ||||
| */ | ||||
| BotNotifyBotEvent( msg, a, b, c, d, e, f, g ) | ||||
| { | ||||
| 	self notify( "bot_event", msg, a, b, c, d, e, f, g ); | ||||
| 	self thread BotNotifyBotEvent_( msg, a, b, c, d, e, f, g ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -1252,7 +1284,6 @@ readWpsFromFile( mapname ) | ||||
| */ | ||||
| load_waypoints() | ||||
| { | ||||
| 	level.waypointcount = 0; | ||||
| 	level.waypointusage = []; | ||||
| 	level.waypointusage[ "allies" ] = []; | ||||
| 	level.waypointusage[ "axis" ] = []; | ||||
| @@ -1291,9 +1322,7 @@ load_waypoints() | ||||
| 		BotBuiltinPrintConsole( "No waypoints loaded!" ); | ||||
| 	} | ||||
| 	 | ||||
| 	level.waypointcount = level.waypoints.size; | ||||
| 	 | ||||
| 	for ( i = 0; i < level.waypointcount; i++ ) | ||||
| 	for ( i = level.waypoints.size - 1; i >= 0; i-- ) | ||||
| 	{ | ||||
| 		if ( !isdefined( level.waypoints[ i ].children ) || !isdefined( level.waypoints[ i ].children.size ) ) | ||||
| 		{ | ||||
| @@ -1390,7 +1419,7 @@ getWaypointsOfType( type ) | ||||
| { | ||||
| 	answer = []; | ||||
| 	 | ||||
| 	for ( i = 0; i < level.waypointcount; i++ ) | ||||
| 	for ( i = level.waypoints.size - 1; i >= 0; i-- ) | ||||
| 	{ | ||||
| 		wp = level.waypoints[ i ]; | ||||
| 		 | ||||
| @@ -2107,16 +2136,18 @@ RemoveWaypointUsage( wp, team ) | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( !isdefined( level.waypointusage[ team ][ wp + "" ] ) ) | ||||
| 	wpstr = wp + ""; | ||||
| 	 | ||||
| 	if ( !isdefined( level.waypointusage[ team ][ wpstr ] ) ) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	level.waypointusage[ team ][ wp + "" ]--; | ||||
| 	level.waypointusage[ team ][ wpstr ]--; | ||||
| 	 | ||||
| 	if ( level.waypointusage[ team ][ wp + "" ] <= 0 ) | ||||
| 	if ( level.waypointusage[ team ][ wpstr ] <= 0 ) | ||||
| 	{ | ||||
| 		level.waypointusage[ team ][ wp + "" ] = undefined; | ||||
| 		level.waypointusage[ team ][ wpstr ] = undefined; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -2128,7 +2159,7 @@ GetNearestWaypointWithSight( pos ) | ||||
| 	candidate = undefined; | ||||
| 	dist = 2147483647; | ||||
| 	 | ||||
| 	for ( i = 0; i < level.waypointcount; i++ ) | ||||
| 	for ( i = level.waypoints.size - 1; i >= 0; i-- ) | ||||
| 	{ | ||||
| 		if ( !bullettracepassed( pos + ( 0, 0, 15 ), level.waypoints[ i ].origin + ( 0, 0, 15 ), false, undefined ) ) | ||||
| 		{ | ||||
| @@ -2157,7 +2188,7 @@ getNearestWaypoint( pos ) | ||||
| 	candidate = undefined; | ||||
| 	dist = 2147483647; | ||||
| 	 | ||||
| 	for ( i = 0; i < level.waypointcount; i++ ) | ||||
| 	for ( i = level.waypoints.size - 1; i >= 0; i-- ) | ||||
| 	{ | ||||
| 		curdis = distancesquared( level.waypoints[ i ].origin, pos ); | ||||
| 		 | ||||
| @@ -2242,7 +2273,8 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 		// pop bestnode from queue | ||||
| 		bestNode = open.data[ 0 ]; | ||||
| 		open HeapRemove(); | ||||
| 		openset[ bestNode.index + "" ] = undefined; | ||||
| 		bestNodeStr = bestNode.index + ""; | ||||
| 		openset[ bestNodeStr ] = undefined; | ||||
| 		wp = level.waypoints[ bestNode.index ]; | ||||
| 		 | ||||
| 		// check if we made it to the goal | ||||
| @@ -2252,14 +2284,16 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 			 | ||||
| 			while ( isdefined( bestNode ) ) | ||||
| 			{ | ||||
| 				bestNodeStr = bestNode.index + ""; | ||||
| 				 | ||||
| 				if ( isdefined( team ) && isdefined( level.waypointusage ) ) | ||||
| 				{ | ||||
| 					if ( !isdefined( level.waypointusage[ team ][ bestNode.index + "" ] ) ) | ||||
| 					if ( !isdefined( level.waypointusage[ team ][ bestNodeStr ] ) ) | ||||
| 					{ | ||||
| 						level.waypointusage[ team ][ bestNode.index + "" ] = 0; | ||||
| 						level.waypointusage[ team ][ bestNodeStr ] = 0; | ||||
| 					} | ||||
| 					 | ||||
| 					level.waypointusage[ team ][ bestNode.index + "" ]++; | ||||
| 					level.waypointusage[ team ][ bestNodeStr ]++; | ||||
| 				} | ||||
| 				 | ||||
| 				// construct path | ||||
| @@ -2275,6 +2309,7 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 		for ( i = wp.children.size - 1; i >= 0; i-- ) | ||||
| 		{ | ||||
| 			child = wp.children[ i ]; | ||||
| 			childStr = child + ""; | ||||
| 			childWp = level.waypoints[ child ]; | ||||
| 			 | ||||
| 			penalty = 1; | ||||
| @@ -2283,9 +2318,9 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 			{ | ||||
| 				temppen = 1; | ||||
| 				 | ||||
| 				if ( isdefined( level.waypointusage[ team ][ child + "" ] ) ) | ||||
| 				if ( isdefined( level.waypointusage[ team ][ childStr ] ) ) | ||||
| 				{ | ||||
| 					temppen = level.waypointusage[ team ][ child + "" ]; // consider how many bots are taking this path | ||||
| 					temppen = level.waypointusage[ team ][ childStr ]; // consider how many bots are taking this path | ||||
| 				} | ||||
| 				 | ||||
| 				if ( temppen > 1 ) | ||||
| @@ -2304,16 +2339,16 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 			newg = bestNode.g + distancesquared( wp.origin, childWp.origin ) * penalty; // bots on same team's path are more expensive | ||||
| 			 | ||||
| 			// check if this child is in open or close with a g value less than newg | ||||
| 			inopen = isdefined( openset[ child + "" ] ); | ||||
| 			inopen = isdefined( openset[ childStr ] ); | ||||
| 			 | ||||
| 			if ( inopen && openset[ child + "" ].g <= newg ) | ||||
| 			if ( inopen && openset[ childStr ].g <= newg ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| 			 | ||||
| 			inclosed = isdefined( closed[ child + "" ] ); | ||||
| 			inclosed = isdefined( closed[ childStr ] ); | ||||
| 			 | ||||
| 			if ( inclosed && closed[ child + "" ].g <= newg ) | ||||
| 			if ( inclosed && closed[ childStr ].g <= newg ) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
| @@ -2322,11 +2357,11 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 			 | ||||
| 			if ( inopen ) | ||||
| 			{ | ||||
| 				node = openset[ child + "" ]; | ||||
| 				node = openset[ childStr ]; | ||||
| 			} | ||||
| 			else if ( inclosed ) | ||||
| 			{ | ||||
| 				node = closed[ child + "" ]; | ||||
| 				node = closed[ childStr ]; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| @@ -2342,19 +2377,19 @@ AStarSearch( start, goal, team, greedy_path ) | ||||
| 			// check if in closed, remove it | ||||
| 			if ( inclosed ) | ||||
| 			{ | ||||
| 				closed[ child + "" ] = undefined; | ||||
| 				closed[ childStr ] = undefined; | ||||
| 			} | ||||
| 			 | ||||
| 			// check if not in open, add it | ||||
| 			if ( !inopen ) | ||||
| 			{ | ||||
| 				open HeapInsert( node ); | ||||
| 				openset[ child + "" ] = node; | ||||
| 				openset[ childStr ] = node; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		// done with children, push onto closed | ||||
| 		closed[ bestNode.index + "" ] = bestNode; | ||||
| 		closed[ bestNodeStr ] = bestNode; | ||||
| 	} | ||||
| 	 | ||||
| 	return []; | ||||
| @@ -3697,3 +3732,169 @@ playerModelForWeapon( weapon, secondary ) | ||||
| 		[[ game[ team + "_model" ][ "JUGGERNAUT" ] ]](); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Make player ref attach to rocket ent | ||||
| */ | ||||
| tryUsePredatorMissileFix( lifeId ) | ||||
| { | ||||
| 	if ( isdefined( level.civilianjetflyby ) ) | ||||
| 	{ | ||||
| 		self iprintlnbold( &"MP_CIVILIAN_AIR_TRAFFIC" ); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	self setusingremote( "remotemissile" ); | ||||
| 	result = self maps\mp\killstreaks\_killstreaks::initridekillstreak(); | ||||
| 	 | ||||
| 	if ( result != "success" ) | ||||
| 	{ | ||||
| 		if ( result != "disconnect" ) | ||||
| 		{ | ||||
| 			self clearusingremote(); | ||||
| 		} | ||||
| 		 | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	level thread _fireFix( lifeId, self ); | ||||
| 	 | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Make player ref attach to rocket ent | ||||
| */ | ||||
| _fireFix( lifeId, player ) | ||||
| { | ||||
| 	remoteMissileSpawnArray = getentarray( "remoteMissileSpawn", "targetname" ); | ||||
| 	//assertEX( remoteMissileSpawnArray.size > 0 && getMapCustom( "map" ) != "", "No remote missile spawn points found.  Contact friendly neighborhood designer" ); | ||||
| 	 | ||||
| 	foreach ( spawn in remoteMissileSpawnArray ) | ||||
| 	{ | ||||
| 		if ( isdefined( spawn.target ) ) | ||||
| 		{ | ||||
| 			spawn.targetent = getent( spawn.target, "targetname" ); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	if ( remoteMissileSpawnArray.size > 0 ) | ||||
| 	{ | ||||
| 		remoteMissileSpawn = player maps\mp\killstreaks\_remotemissile::getbestspawnpoint( remoteMissileSpawnArray ); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		remoteMissileSpawn = undefined; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( isdefined( remoteMissileSpawn ) ) | ||||
| 	{ | ||||
| 		startPos = remoteMissileSpawn.origin; | ||||
| 		targetPos = remoteMissileSpawn.targetent.origin; | ||||
| 		 | ||||
| 		//thread drawLine( startPos, targetPos, 30, (0,1,0) ); | ||||
| 		 | ||||
| 		vector = vectornormalize( startPos - targetPos ); | ||||
| 		startPos = vector * 14000 + targetPos; | ||||
| 		 | ||||
| 		//thread drawLine( startPos, targetPos, 15, (1,0,0) ); | ||||
| 		 | ||||
| 		rocket = magicbullet( "remotemissile_projectile_mp", startpos, targetPos, player ); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		upVector = ( 0, 0, level.missileremotelaunchvert ); | ||||
| 		backDist = level.missileremotelaunchhorz; | ||||
| 		targetDist = level.missileremotelaunchtargetdist; | ||||
| 		 | ||||
| 		forward = anglestoforward( player.angles ); | ||||
| 		startpos = player.origin + upVector + forward * backDist * -1; | ||||
| 		targetPos = player.origin + forward * targetDist; | ||||
| 		 | ||||
| 		rocket = magicbullet( "remotemissile_projectile_mp", startpos, targetPos, player ); | ||||
| 	} | ||||
| 	 | ||||
| 	if ( !isdefined( rocket ) ) | ||||
| 	{ | ||||
| 		player clearusingremote(); | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	rocket thread maps\mp\gametypes\_weapons::addmissiletosighttraces( player.team ); | ||||
| 	 | ||||
| 	// rocket thread maps\mp\killstreaks\_remotemissile::handledamage(); // gsc-tool wrong token, its okay, this func is useless anyway | ||||
| 	 | ||||
| 	rocket.lifeid = lifeId; | ||||
| 	rocket.type = "remote"; | ||||
| 	MissileEyesFix( player, rocket ); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	Make player ref attach to rocket ent | ||||
| */ | ||||
| MissileEyesFix( player, rocket ) | ||||
| { | ||||
| 	//level endon ( "game_ended" ); | ||||
| 	player endon( "joined_team" ); | ||||
| 	player endon( "joined_spectators" ); | ||||
| 	 | ||||
| 	rocket thread maps\mp\killstreaks\_remotemissile::rocket_cleanupondeath(); | ||||
| 	player thread maps\mp\killstreaks\_remotemissile::player_cleanupongameended( rocket ); | ||||
| 	player thread maps\mp\killstreaks\_remotemissile::player_cleanuponteamchange( rocket ); | ||||
| 	 | ||||
| 	player visionsetmissilecamforplayer( "black_bw", 0 ); | ||||
| 	 | ||||
| 	player endon ( "disconnect" ); | ||||
| 	 | ||||
| 	if ( isdefined( rocket ) ) | ||||
| 	{ | ||||
| 		player visionsetmissilecamforplayer( game["thermal_vision"], 1.0 ); | ||||
| 		player thermalvisionon(); | ||||
| 		player thread maps\mp\killstreaks\_remotemissile::delayedfofoverlay(); | ||||
| 		player cameralinkto( rocket, "tag_origin" ); | ||||
| 		player controlslinkto( rocket ); | ||||
| 		 | ||||
| 		// our additions | ||||
| 		player.rocket = rocket; | ||||
| 		rocket.owner = player; | ||||
| 		 | ||||
| 		if ( getdvarint( "camera_thirdPerson" ) ) | ||||
| 		{ | ||||
| 			player setthirdpersondof( false ); | ||||
| 		} | ||||
| 		 | ||||
| 		rocket waittill( "death" ); | ||||
| 		player thermalvisionoff(); | ||||
| 		 | ||||
| 		// is defined check required because remote missile doesnt handle lifetime explosion gracefully | ||||
| 		// instantly deletes its self after an explode and death notify | ||||
| 		if ( isdefined( rocket ) ) | ||||
| 		{ | ||||
| 			player maps\mp\_matchdata::logkillstreakevent( "predator_missile", rocket.origin ); | ||||
| 		} | ||||
| 		 | ||||
| 		player controlsunlink(); | ||||
| 		player freezecontrolswrapper( true ); | ||||
| 		player.rocket = undefined; // our addition | ||||
| 		 | ||||
| 		// If a player gets the final kill with a hellfire, level.gameEnded will already be true at this point | ||||
| 		if ( !level.gameended || isdefined( player.finalkill ) ) | ||||
| 		{ | ||||
| 			player thread maps\mp\killstreaks\_remotemissile::staticeffect( 0.5 ); | ||||
| 		} | ||||
| 		 | ||||
| 		wait ( 0.5 ); | ||||
| 		 | ||||
| 		player thermalvisionfofoverlayoff(); | ||||
| 		 | ||||
| 		player cameraunlink(); | ||||
| 		 | ||||
| 		if ( getdvarint( "camera_thirdPerson" ) ) | ||||
| 		{ | ||||
| 			player setthirdpersondof( true ); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 	 | ||||
| 	player clearusingremote(); | ||||
| } | ||||
|   | ||||
| @@ -55,6 +55,50 @@ watchPlayers() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| destroyFixed() | ||||
| { | ||||
| 	if ( !isdefined( self ) ) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	self destroy(); | ||||
| } | ||||
|  | ||||
| removeChildFixed( element ) | ||||
| { | ||||
| 	temp = []; | ||||
| 	 | ||||
| 	for ( i = 0; i < self.children.size ; i++ ) | ||||
| 	{ | ||||
| 		if ( isdefined( self.children[ i ] ) && self.children[ i ] != element ) | ||||
| 		{ | ||||
| 			self.children[ i ].index = temp.size; | ||||
| 			temp[ temp.size ] = self.children[ i ]; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	self.children = temp; | ||||
| 	 | ||||
| 	element.index = undefined; | ||||
| 	element.parent = undefined; | ||||
| } | ||||
|  | ||||
| destroyElemFixed() | ||||
| { | ||||
| 	if ( !isdefined( self ) ) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	if ( isdefined( self.parent ) ) | ||||
| 	{ | ||||
| 		self.parent removeChildFixed( self ); | ||||
| 	} | ||||
| 	 | ||||
| 	self destroyelem(); | ||||
| } | ||||
|  | ||||
| kill_menu() | ||||
| { | ||||
| 	self notify( "bots_kill_menu" ); | ||||
| @@ -66,7 +110,6 @@ init_menu() | ||||
| 	self.menuinit = true; | ||||
| 	 | ||||
| 	self.menuopen = false; | ||||
| 	self.menu_player = undefined; | ||||
| 	self.submenu = "Main"; | ||||
| 	self.curs[ "Main" ][ "X" ] = 0; | ||||
| 	self addOptions(); | ||||
| @@ -95,7 +138,7 @@ watchDisconnect() | ||||
| 			{ | ||||
| 				if ( isdefined( self.menutexty[ i ] ) ) | ||||
| 				{ | ||||
| 					self.menutexty[ i ] destroy(); | ||||
| 					self.menutexty[ i ] destroyElemFixed(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -106,7 +149,7 @@ watchDisconnect() | ||||
| 			{ | ||||
| 				if ( isdefined( self.menutext[ i ] ) ) | ||||
| 				{ | ||||
| 					self.menutext[ i ] destroy(); | ||||
| 					self.menutext[ i ] destroyElemFixed(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -115,18 +158,18 @@ watchDisconnect() | ||||
| 		{ | ||||
| 			if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) | ||||
| 			{ | ||||
| 				self.menu[ "X" ][ "Shader" ] destroy(); | ||||
| 				self.menu[ "X" ][ "Shader" ] destroyElemFixed(); | ||||
| 			} | ||||
| 			 | ||||
| 			if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) | ||||
| 			{ | ||||
| 				self.menu[ "X" ][ "Scroller" ] destroy(); | ||||
| 				self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		if ( isdefined( self.menuversionhud ) ) | ||||
| 		{ | ||||
| 			self.menuversionhud destroy(); | ||||
| 			self.menuversionhud destroyFixed(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -332,7 +375,7 @@ OpenSub( menu, menu2 ) | ||||
| 			{ | ||||
| 				if ( isdefined( self.menutext[ i ] ) ) | ||||
| 				{ | ||||
| 					self.menutext[ i ] destroy(); | ||||
| 					self.menutext[ i ] destroyElemFixed(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -341,18 +384,18 @@ OpenSub( menu, menu2 ) | ||||
| 		{ | ||||
| 			if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) | ||||
| 			{ | ||||
| 				self.menu[ "X" ][ "Shader" ] destroy(); | ||||
| 				self.menu[ "X" ][ "Shader" ] destroyElemFixed(); | ||||
| 			} | ||||
| 			 | ||||
| 			if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) | ||||
| 			{ | ||||
| 				self.menu[ "X" ][ "Scroller" ] destroy(); | ||||
| 				self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		if ( isdefined( self.menuversionhud ) ) | ||||
| 		{ | ||||
| 			self.menuversionhud destroy(); | ||||
| 			self.menuversionhud destroyFixed(); | ||||
| 		} | ||||
| 		 | ||||
| 		for ( i = 0 ; i < self.option[ "Name" ][ self.submenu ].size ; i++ ) | ||||
| @@ -402,7 +445,7 @@ OpenSub( menu, menu2 ) | ||||
| 			{ | ||||
| 				if ( isdefined( self.menutexty[ i ] ) ) | ||||
| 				{ | ||||
| 					self.menutexty[ i ] destroy(); | ||||
| 					self.menutexty[ i ] destroyElemFixed(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -426,11 +469,11 @@ CursMove( direction ) | ||||
| 	 | ||||
| 	if ( self.submenu == "Main" ) | ||||
| 	{ | ||||
| 		self.menu[ "X" ][ "Scroller" ].x = self.menutext[ self.curs[ "Main" ][ "X" ] ].x; | ||||
| 		self.menu[ "X" ][ "Scroller" ].y = self.menutext[ self.curs[ "Main" ][ "X" ] ].y; | ||||
| 		 | ||||
| 		if ( isdefined( self.menutext ) ) | ||||
| 		{ | ||||
| 			self.menu[ "X" ][ "Scroller" ].x = self.menutext[ self.curs[ "Main" ][ "X" ] ].x; | ||||
| 			self.menu[ "X" ][ "Scroller" ].y = self.menutext[ self.curs[ "Main" ][ "X" ] ].y; | ||||
| 			 | ||||
| 			for ( i = 0; i < self.menutext.size; i++ ) | ||||
| 			{ | ||||
| 				if ( isdefined( self.menutext[ i ] ) ) | ||||
| @@ -578,7 +621,7 @@ ExitSub() | ||||
| 		{ | ||||
| 			if ( isdefined( self.menutexty[ i ] ) ) | ||||
| 			{ | ||||
| 				self.menutexty[ i ] destroy(); | ||||
| 				self.menutexty[ i ] destroyElemFixed(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -603,7 +646,7 @@ ExitMenu() | ||||
| 		{ | ||||
| 			if ( isdefined( self.menutext[ i ] ) ) | ||||
| 			{ | ||||
| 				self.menutext[ i ] destroy(); | ||||
| 				self.menutext[ i ] destroyElemFixed(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -612,18 +655,18 @@ ExitMenu() | ||||
| 	{ | ||||
| 		if ( isdefined( self.menu[ "X" ][ "Shader" ] ) ) | ||||
| 		{ | ||||
| 			self.menu[ "X" ][ "Shader" ] destroy(); | ||||
| 			self.menu[ "X" ][ "Shader" ] destroyElemFixed(); | ||||
| 		} | ||||
| 		 | ||||
| 		if ( isdefined( self.menu[ "X" ][ "Scroller" ] ) ) | ||||
| 		{ | ||||
| 			self.menu[ "X" ][ "Scroller" ] destroy(); | ||||
| 			self.menu[ "X" ][ "Scroller" ] destroyElemFixed(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	if ( isdefined( self.menuversionhud ) ) | ||||
| 	{ | ||||
| 		self.menuversionhud destroy(); | ||||
| 		self.menuversionhud destroyFixed(); | ||||
| 	} | ||||
| 	 | ||||
| 	self.menuopen = false; | ||||
| @@ -728,6 +771,10 @@ addOptions() | ||||
| 			_temp = "bots used as team balance"; | ||||
| 			break; | ||||
| 			 | ||||
| 		case 5: | ||||
| 			_temp = "bots used as team balance, adjust to map"; | ||||
| 			break; | ||||
| 			 | ||||
| 		default: | ||||
| 			_temp = "out of range"; | ||||
| 			break; | ||||
| @@ -1320,6 +1367,11 @@ man_bots( a, b ) | ||||
| 					self iprintln( "bot_fill will now use bots as team balance." ); | ||||
| 					break; | ||||
| 					 | ||||
| 				case 4: | ||||
| 					setdvar( "bots_manage_fill_mode", 5 ); | ||||
| 					self iprintln( "bot_fill will now use bots as team balance, adjusting to map." ); | ||||
| 					break; | ||||
| 					 | ||||
| 				default: | ||||
| 					setdvar( "bots_manage_fill_mode", 0 ); | ||||
| 					self iprintln( "bot_fill will now count everyone." ); | ||||
|   | ||||
| @@ -77,7 +77,7 @@ init() | ||||
| 		level.waypoints = []; | ||||
| 	} | ||||
| 	 | ||||
| 	level.waypointcount = 0; | ||||
| 	level.waypointcount = level.waypoints.size; | ||||
| 	 | ||||
| 	level waittill( "connected", player ); | ||||
| 	player thread onPlayerSpawned(); | ||||
| @@ -153,29 +153,29 @@ watchAstarCommand() | ||||
| 	self endon( "death" ); | ||||
| 	 | ||||
| 	self notifyonplayercommand( "astar", "+gostand" ); | ||||
| 	self.astar = undefined; | ||||
| 	 | ||||
| 	for ( ;; ) | ||||
| 	{ | ||||
| 		self waittill( "astar" ); | ||||
| 		 | ||||
| 		if ( 1 ) | ||||
| 		if ( isdefined( self.astar ) ) | ||||
| 		{ | ||||
| 			continue; | ||||
| 			self iprintln( "Clear AStar" ); | ||||
| 			self.astar = undefined; | ||||
| 			self waittill( "astar" ); | ||||
| 		} | ||||
| 		 | ||||
| 		self iprintln( "Start AStar" ); | ||||
| 		self.astar = undefined; | ||||
| 		astar = spawnstruct(); | ||||
| 		astar.start = self.origin; | ||||
| 		self.astar = spawnstruct(); | ||||
| 		self.astar.start = self.origin; | ||||
| 		 | ||||
| 		self waittill( "astar" ); | ||||
| 		self iprintln( "End AStar" ); | ||||
| 		astar.goal = self.origin; | ||||
| 		self.astar.goal = self.origin; | ||||
| 		 | ||||
| 		astar.nodes = AStarSearch( astar.start, astar.goal, undefined, true ); | ||||
| 		self iprintln( "AStar size: " + astar.nodes.size ); | ||||
| 		 | ||||
| 		self.astar = astar; | ||||
| 		self.astar.nodes = AStarSearch( self.astar.start, self.astar.goal, undefined, true ); | ||||
| 		self iprintln( "AStar size: " + self.astar.nodes.size ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -405,30 +405,45 @@ updateWaypointsStats() | ||||
| 		 | ||||
| 		if ( isdefined( self.astar ) ) | ||||
| 		{ | ||||
| 			// print3d(self.astar.start + (0, 0, 35), "start", (0,0,1), 2); | ||||
| 			// print3d(self.astar.goal + (0, 0, 35), "goal", (0,0,1), 2); | ||||
| 			if ( timeToUpdate ) | ||||
| 			if ( isdefined( self.astar.start ) ) | ||||
| 			{ | ||||
| 				drawPath( self.astar.start ); | ||||
| 				drawPath( self.astar.goal ); | ||||
| 			} | ||||
| 				// print3d( self.astar.start + ( 0, 0, 35 ), "start", ( 0, 0, 1 ), 2 ); | ||||
| 				 | ||||
| 			prev = self.astar.start + ( 0, 0, 35 ); | ||||
| 			 | ||||
| 			for ( i = self.astar.nodes.size - 1; i >= 0; i-- ) | ||||
| 			{ | ||||
| 				node = self.astar.nodes[ i ]; | ||||
| 				 | ||||
| 				// line(prev, level.waypoints[ node ].origin + (0, 0, 35), (0,1,1)); | ||||
| 				if ( timeToUpdate ) | ||||
| 				{ | ||||
| 					drawPath( level.waypoints[ node ].origin ); | ||||
| 					drawPath( self.astar.start ); | ||||
| 				} | ||||
| 				 | ||||
| 				prev = level.waypoints[ node ].origin + ( 0, 0, 35 ); | ||||
| 			} | ||||
| 			 | ||||
| 			// line(prev, self.astar.goal + (0, 0, 35), (0,1,1)); | ||||
| 			if ( isdefined( self.astar.goal ) ) | ||||
| 			{ | ||||
| 				// print3d( self.astar.goal + ( 0, 0, 35 ), "goal", ( 0, 0, 1 ), 2 ); | ||||
| 				 | ||||
| 				if ( timeToUpdate ) | ||||
| 				{ | ||||
| 					drawPath( self.astar.goal ); | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			if ( isdefined( self.astar.start ) && isdefined( self.astar.goal ) && isdefined( self.astar.nodes ) ) | ||||
| 			{ | ||||
| 				prev = self.astar.start + ( 0, 0, 35 ); | ||||
| 				 | ||||
| 				for ( i = self.astar.nodes.size - 1; i >= 0; i-- ) | ||||
| 				{ | ||||
| 					node = self.astar.nodes[ i ]; | ||||
| 					 | ||||
| 					// line(prev, level.waypoints[ node ].origin + (0, 0, 35), (0,1,1)); | ||||
| 					if ( timeToUpdate ) | ||||
| 					{ | ||||
| 						drawPath( level.waypoints[ node ].origin ); | ||||
| 					} | ||||
| 					 | ||||
| 					prev = level.waypoints[ node ].origin + ( 0, 0, 35 ); | ||||
| 				} | ||||
| 				 | ||||
| 				// line(prev, self.astar.goal + (0, 0, 35), (0,1,1)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -646,6 +661,7 @@ LoadWaypoints() | ||||
| 	// self DeleteAllWaypoints(); | ||||
| 	self iprintlnbold( "Loading WPS..." ); | ||||
| 	load_waypoints(); | ||||
| 	level.waypointcount = level.waypoints.size; | ||||
| 	 | ||||
| 	wait 1; | ||||
| 	 | ||||
| @@ -934,7 +950,7 @@ DeleteAllWaypoints() | ||||
| 	self iprintln( "DelAllWps" ); | ||||
| } | ||||
|  | ||||
| buildChildCountString ( wp ) | ||||
| buildChildCountString( wp ) | ||||
| { | ||||
| 	if ( wp == -1 ) | ||||
| 	{ | ||||
|   | ||||
| @@ -8,6 +8,8 @@ init() | ||||
| 	level.bot_builtins["botstop"] = ::do_botstop; | ||||
| 	level.bot_builtins["botmovement"] = ::do_botmovement; | ||||
| 	level.bot_builtins["botmeleeparams"] = ::do_botmeleeparams; | ||||
| 	level.bot_builtins[ "botremoteangles" ] = ::do_botremoteangles; | ||||
| 	level.bot_builtins[ "botangles" ] = ::do_botangles; | ||||
| } | ||||
|  | ||||
| do_printconsole( s ) | ||||
| @@ -51,3 +53,13 @@ do_botmeleeparams( entNum, dist ) | ||||
| { | ||||
| 	self botmeleeparams( entNum, dist ); | ||||
| } | ||||
|  | ||||
| do_botremoteangles( pitch, yaw ) | ||||
| { | ||||
| 	self botremoteangles( pitch, yaw ); | ||||
| } | ||||
|  | ||||
| do_botangles( angles ) | ||||
| { | ||||
| 	self botangles( angles[ 0 ], angles[ 1 ], angles[ 2 ] ); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user