1 ///////////////////////////////////////////////////////////////////////
2 //
3 //  ACE - Quake II Bot Base Code
4 //
5 //  Version 1.0
6 //
7 //  This file is Copyright(c), Steve Yeager 1998, All Rights Reserved
8 //
9 //
10 //	All other files are Copyright(c) Id Software, Inc.
11 //
12 //	Please see liscense.txt in the source directory for the copyright
13 //	information regarding those files belonging to Id Software, Inc.
14 //
15 //	Should you decide to release a modified version of ACE, you MUST
16 //	include the following text (minus the BEGIN and END lines) in the
17 //	documentation for your modification.
18 //
19 //	--- BEGIN ---
20 //
21 //	The ACE Bot is a product of Steve Yeager, and is available from
22 //	the ACE Bot homepage, at http://www.axionfx.com/ace.
23 //
24 //	This program is a modification of the ACE Bot, and is therefore
25 //	in NO WAY supported by Steve Yeager.
26 
27 //	This program MUST NOT be sold in ANY form. If you have paid for
28 //	this product, you should contact Steve Yeager immediately, via
29 //	the ACE Bot homepage.
30 //
31 //	--- END ---
32 //
33 //	I, Steve Yeager, hold no responsibility for any harm caused by the
34 //	use of this source code, especially to small children and animals.
35 //  It is provided as-is with no implied warranty or support.
36 //
37 //  I also wish to thank and acknowledge the great work of others
38 //  that has helped me to develop this code.
39 //
40 //  John Cricket    - For ideas and swapping code.
41 //  Ryan Feltrin    - For ideas and swapping code.
42 //  SABIN           - For showing how to do true client based movement.
43 //  BotEpidemic     - For keeping us up to date.
44 //  Telefragged.com - For giving ACE a home.
45 //  Microsoft       - For giving us such a wonderful crash free OS.
46 //  id              - Need I say more.
47 //
48 //  And to all the other testers, pathers, and players and people
49 //  who I can't remember who the heck they were, but helped out.
50 //
51 ///////////////////////////////////////////////////////////////////////
52 
53 ///////////////////////////////////////////////////////////////////////
54 //
55 //  acebot_cmds.c - Main internal command processor
56 //
57 ///////////////////////////////////////////////////////////////////////
58 
59 #ifdef HAVE_CONFIG_H
60 #include "config.h"
61 #endif
62 
63 #include "game/g_local.h"
64 #include "acebot.h"
65 
66 qboolean debug_mode=false;
67 
68 ///////////////////////////////////////////////////////////////////////
69 // Special command processor
70 ///////////////////////////////////////////////////////////////////////
ACECM_Commands(edict_t * ent)71 qboolean ACECM_Commands(edict_t *ent)
72 {
73 	char	*cmd;
74 	int node;
75 
76 	cmd = gi.argv(0);
77 
78 	if(Q_strcasecmp (cmd, "addnode") == 0 && debug_mode)
79 		ent->last_node = ACEND_AddNode(ent,atoi(gi.argv(1)));
80 
81 	else if(Q_strcasecmp (cmd, "removelink") == 0 && debug_mode)
82 		ACEND_RemoveNodeEdge(ent,atoi(gi.argv(1)), atoi(gi.argv(2)));
83 
84 	else if(Q_strcasecmp (cmd, "addlink") == 0 && debug_mode)
85 		ACEND_UpdateNodeEdge(atoi(gi.argv(1)), atoi(gi.argv(2)));
86 
87 	else if(Q_strcasecmp (cmd, "showpath") == 0 && debug_mode)
88     	ACEND_ShowPath(ent,atoi(gi.argv(1)));
89 
90     else if(Q_strcasecmp (cmd, "shownode") == 0 && debug_mode)
91     	ACEND_ShowNode(atoi(gi.argv(1)));
92 
93     else if(Q_strcasecmp (cmd, "hidenode") == 0 && debug_mode)
94     {
95         node = atoi(gi.argv(1));
96         if (node_showents[node])
97         {
98             G_FreeEdict(node_showents[node]);
99             node_showents[node] = NULL;
100         }
101     }
102 
103 	else if(Q_strcasecmp (cmd, "findnode") == 0 && debug_mode)
104 	{
105 	    if (gi.argc() == 2)
106 	        node = atoi(gi.argv(1));
107 	    else
108 		    node = ACEND_FindClosestReachableNode(ent,NODE_DENSITY, NODE_ALL);
109 		safe_bprintf(PRINT_MEDIUM,"node: %d type: %d x: %f y: %f z %f\n",node,nodes[node].type,nodes[node].origin[0],nodes[node].origin[1],nodes[node].origin[2]);
110 	}
111 
112 	else if(Q_strcasecmp (cmd, "movenode") == 0 && debug_mode)
113 	{
114 		node = atoi(gi.argv(1));
115 		nodes[node].origin[0] = atof(gi.argv(2));
116 		nodes[node].origin[1] = atof(gi.argv(3));
117 		nodes[node].origin[2] = atof(gi.argv(4));
118 		safe_bprintf(PRINT_MEDIUM,"node: %d moved to x: %f y: %f z %f\n",node, nodes[node].origin[0],nodes[node].origin[1],nodes[node].origin[2]);
119 	}
120 
121 	else
122 		return false;
123 
124 	return true;
125 }
126 
127 
128 ///////////////////////////////////////////////////////////////////////
129 // Called when the level changes, store maps and bots (disconnected)
130 ///////////////////////////////////////////////////////////////////////
ACECM_Store()131 void ACECM_Store()
132 {
133 	ACEND_SaveNodes();
134 }
135 
136 ///////////////////////////////////////////////////////////////////////
137 // These routines are bot safe print routines, all id code needs to be
138 // changed to these so the bots do not blow up on messages sent to them.
139 // Do a find and replace on all code that matches the below criteria.
140 //
141 // (Got the basic idea from Ridah)
142 //
143 //  change: gi.cprintf to safe_cprintf
144 //  change: gi.bprintf to safe_bprintf
145 //  change: gi.centerprintf to safe_centerprintf
146 //
147 ///////////////////////////////////////////////////////////////////////
148 
149 ///////////////////////////////////////////////////////////////////////
150 // Debug print, could add a "logging" feature to print to a file
151 ///////////////////////////////////////////////////////////////////////
debug_printf(char * fmt,...)152 void debug_printf(char *fmt, ...)
153 {
154 	int     i;
155 	char	bigbuffer[0x10000];
156 	int		len;
157 	va_list	argptr;
158 	edict_t	*cl_ent;
159 
160 	va_start (argptr,fmt);
161 	len = vsnprintf (bigbuffer,sizeof(bigbuffer),fmt,argptr);
162 	va_end (argptr);
163 
164 	if (g_dedicated->value)
165 		gi.cprintf(NULL, PRINT_MEDIUM, "%s", bigbuffer);
166 
167 	for (i=0 ; i<g_maxclients->value ; i++)
168 	{
169 		cl_ent = g_edicts + 1 + i;
170 		if (!cl_ent->inuse || cl_ent->is_bot)
171 			continue;
172 
173 		gi.cprintf(cl_ent,  PRINT_MEDIUM, "%s", bigbuffer);
174 	}
175 
176 }
177 
178 ///////////////////////////////////////////////////////////////////////
179 // botsafe cprintf
180 ///////////////////////////////////////////////////////////////////////
safe_cprintf(edict_t * ent,int printlevel,char * fmt,...)181 void safe_cprintf (edict_t *ent, int printlevel, char *fmt, ...)
182 {
183 	char	bigbuffer[0x10000];
184 	va_list		argptr;
185 	int len;
186 
187 	if (ent && (!ent->inuse || ent->is_bot))
188 		return;
189 
190 	va_start (argptr,fmt);
191 	len = vsnprintf (bigbuffer,sizeof(bigbuffer),fmt,argptr);
192 	va_end (argptr);
193 
194 	gi.cprintf(ent, printlevel, "%s", bigbuffer);
195 
196 }
197 
198 ///////////////////////////////////////////////////////////////////////
199 // botsafe centerprintf
200 ///////////////////////////////////////////////////////////////////////
safe_centerprintf(edict_t * ent,char * fmt,...)201 void safe_centerprintf (edict_t *ent, char *fmt, ...)
202 {
203 	char	bigbuffer[0x10000];
204 	va_list		argptr;
205 	int len;
206 
207 	if (!ent->inuse || ent->is_bot)
208 		return;
209 
210 	// If the MOTD was displayed and is being "protected" from overwrite,
211 	// ignore the call.
212 	if ( ent->client && ent->client->motd_frames ) {
213 		return;
214 	}
215 
216 	va_start (argptr,fmt);
217 	len = vsnprintf (bigbuffer,sizeof(bigbuffer),fmt,argptr);
218 	va_end (argptr);
219 
220 	gi.centerprintf(ent,"%s", bigbuffer);
221 
222 }
223 
224 ///////////////////////////////////////////////////////////////////////
225 // botsafe bprintf
226 ///////////////////////////////////////////////////////////////////////
safe_bprintf(int printlevel,char * fmt,...)227 void safe_bprintf (int printlevel, char *fmt, ...)
228 {
229 	int i;
230 	char	bigbuffer[0x10000];
231 	int		len;
232 	va_list		argptr;
233 	edict_t	*cl_ent;
234 
235 	va_start (argptr,fmt);
236 	len = vsnprintf (bigbuffer,sizeof(bigbuffer),fmt,argptr);
237 	va_end (argptr);
238 
239 	if (g_dedicated->value)
240 		gi.cprintf(NULL, printlevel, "%s", bigbuffer);
241 
242 	for (i=0 ; i<g_maxclients->value ; i++)
243 	{
244 		cl_ent = g_edicts + 1 + i;
245 		if (!cl_ent->inuse || cl_ent->is_bot)
246 			continue;
247 
248 		gi.cprintf(cl_ent, printlevel, "%s", bigbuffer);
249 	}
250 }
251 
252