1 #include "bot.h"
2 #include "m_player.h"
3 
4 
Get_YenPos(char * Buff,int * curr)5 qboolean Get_YenPos(char *Buff,int *curr)
6 {
7 	int i;
8 
9 	i = *curr + 1;
10 
11 	while(1)
12 	{
13 //		if(i >= strlen(Buff)) return false;
14 		if(Buff[i] == 0 || Buff[i] == 10 || Buff[i] == 13)
15 		{
16 			*curr = i;
17 			return true;
18 		}
19 		if(Buff[i] == '\\')
20 		{
21 			*curr = i;
22 			return true;
23 		}
24 		if(Buff[i] == '\t') Buff[i] = 0;
25 		i++;
26 	}
27 }
28 //----------------------------------------------------------------
29 //Load Bot Info
30 //
31 // Load bot's infomation from 3ZBConfig.cfg
32 //
33 //----------------------------------------------------------------
Load_BotInfo()34 void Load_BotInfo()
35 {
36 	char	MessageSection[50];
37 	char	Buff[1024];
38 	int		i,j,k,l;
39 
40 	FILE	*fp;
41 
42 	SpawnWaitingBots = 0;
43 	ListedBotCount = 0;
44 
45 	//init message
46 	memset(ClientMessage,0,sizeof(ClientMessage));
47 	//set message section
48 	if(!ctf->value && chedit->value) strcpy(MessageSection,MESS_CHAIN_DM);
49 	else if(ctf->value && !chedit->value) strcpy(MessageSection,MESS_CTF);
50 	else if(ctf->value && chedit->value) strcpy(MessageSection,MESS_CHAIN_CTF);
51 	else strcpy(MessageSection,MESS_DEATHMATCH);
52 
53 	//init botlist
54 	ListedBots = 0;
55 	j = 1;
56 	for(i = 0;i < MAXBOTS;i++)
57 	{
58 		//netname
59 		sprintf(Buff,"Zigock[%i]",i);
60 		strcpy(Bot[i].netname,Buff);
61 		//model
62 		strcpy(Bot[i].model,"male");
63 		//skin
64 		strcpy(Bot[i].model,"grunt");
65 
66 		//param
67 		Bot[i].param[BOP_WALK] = 0;
68 		Bot[i].param[BOP_AIM] = 5;
69 		Bot[i].param[BOP_PICKUP] = 5;
70 		Bot[i].param[BOP_COMBATSKILL] = 5;
71 		Bot[i].param[BOP_ROCJ] = 0;
72 		Bot[i].param[BOP_VRANGE] = 90;
73 		Bot[i].param[BOP_HRANGE] = 180;
74 		Bot[i].param[BOP_REACTION] = 0;
75 
76 		//spawn flag
77 		Bot[i].spflg = 0;
78 		//team
79 		Bot[i].team = j;
80 		if(++j > 2) j = 1;
81 	}
82 
83 	//botlist value
84 	botlist = gi.cvar ("botlist", "default", CVAR_SERVERINFO | CVAR_LATCH);
85 	gamepath = gi.cvar ("game", "0", CVAR_NOSET);
86 
87 	//load info
88 	sprintf(Buff,"%s/3ZBConfig.cfg",gamepath->string);
89 	fp = fopen(Buff,"rt");
90 	if(fp == NULL)
91 	{
92 		gi.dprintf("3ZB CFG: file not found.\n");
93 		return;
94 	}
95 	else
96 	{
97 		fseek( fp, 0, SEEK_SET);	//�擪�ֈړ�
98 		while(1)
99 		{
100 			if(fgets( Buff, sizeof(Buff), fp ) == NULL) goto MESS_NOTFOUND;
101 			if(!_strnicmp(MessageSection,Buff,strlen(MessageSection))) break;
102 		}
103 
104 		while(1)
105 		{
106 			if(fgets( Buff, sizeof(Buff), fp ) == NULL) goto MESS_NOTFOUND;
107 			if(Buff[0] == '.' || Buff[0] == '[' || Buff[0] == '#') break;
108 			k = strlen(Buff);
109 			if((strlen(Buff) + strlen(ClientMessage)) > MAX_STRING_CHARS - 1) break;
110 			strcat(ClientMessage,Buff);
111 		}
112 MESS_NOTFOUND:
113 		//if(botlist->string == NULL) strcpy(MessageSection,BOTLIST_SECTION_DM);
114 		//else
115 		sprintf(MessageSection,"[%s]",botlist->string);
116 		fseek( fp, 0, SEEK_SET);	//�擪�ֈړ�
117 		while(1)
118 		{
119 			if(fgets( Buff, sizeof(Buff), fp ) == NULL)
120 			{
121 				MessageSection[0] = 0;
122 				break;
123 			}
124 			if(!_strnicmp(MessageSection,Buff,strlen(MessageSection))) break;
125 		}
126 		//when not found
127 		if(MessageSection[0] == 0)
128 		{
129 			strcpy(MessageSection,BOTLIST_SECTION_DM);
130 			fseek( fp, 0, SEEK_SET);	//�擪�ֈړ�
131 			while(1)
132 			{
133 				if(fgets( Buff, sizeof(Buff), fp ) == NULL) goto BOTLIST_NOTFOUND;
134 				if(!_strnicmp(MessageSection,Buff,strlen(MessageSection))) break;
135 			}
136 		}
137 
138 		i = 0;
139 		for(i = 0;i < MAXBOTS;i++)
140 		{
141 			if(fgets( Buff, sizeof(Buff), fp ) == NULL) break;
142 			if(Buff[0] == '[') break;
143 			if(Buff[0] == '\n' || Buff[0] == '#') {i--;continue;}
144 			j = 2,k = 1;
145 			if(!strncmp(Buff,"\\\\",2))
146 			{
147 				//netname
148 				if(Get_YenPos(Buff,&k))
149 				{
150 					Buff[k] = 0;
151 					if(strlen(&Buff[j]) < 21) strcpy(Bot[i].netname,&Buff[j]);
152 					j = k + 1;
153 				}
154 				else break;
155 				//model name
156 				if(Get_YenPos(Buff,&k))
157 				{
158 					Buff[k] = 0;
159 					if(strlen(&Buff[j]) < 21) strcpy(Bot[i].model,&Buff[j]);
160 					j = k + 1;
161 					k++;
162 				}
163 				else break;
164 				//skin name
165 				if(Get_YenPos(Buff,&k))
166 				{
167 					Buff[k] = 0;
168 					if(strlen(&Buff[j]) < 21) strcpy(Bot[i].skin,&Buff[j]);
169 					j = k + 1;
170 					k++;
171 				}
172 				else break;
173 				for(l = 0;l < MAXBOP;l++)
174 				{
175 					//param0-7
176 					if(Get_YenPos(Buff,&k))
177 					{
178 						Buff[k] = 0;
179 						Bot[i].param[l] = (unsigned char)atoi(&Buff[j]);
180 						j = k + 1;
181 						k++;
182 					}
183 					else break;
184 				}
185 				if(l < MAXBOP) break;
186 				//team
187 				if(Get_YenPos(Buff,&k))
188 				{
189 					Buff[k] = 0;
190 					if(Buff[j] == 'R') Bot[i].team = 1;
191 					else if(Buff[j] == 'B') Bot[i].team = 2;
192 					else Bot[i].team = 1;
193 					j = k + 1;
194 					k++;
195 				}
196 				else break;
197 				//auto spawn
198 				if(Get_YenPos(Buff,&k))
199 				{
200 					Buff[k] = 0;
201 					Bot[i].spflg = atoi(&Buff[j]);
202 //gi.dprintf("%i %s\n",Bot[i].spflg,&Buff[j]);
203 					if(Bot[i].spflg == BOT_SPRESERVED && autospawn->value && !chedit->value) SpawnWaitingBots++;
204 					else Bot[i].spflg = BOT_SPAWNNOT;
205 				}
206 				else break;
207 				ListedBots++;
208 			}
209 		}
210 	}
211 BOTLIST_NOTFOUND:
212 	fclose(fp);
213 
214 	gi.dprintf("%i of Bots is listed.\n",ListedBots);
215 	spawncycle = level.time + FRAMETIME * 100;
216 }
217 
218 //----------------------------------------------------------------
219 //Get Number of Client
220 //
221 // Total Client
222 //
223 //----------------------------------------------------------------
224 
Get_NumOfPlayer(void)225 int Get_NumOfPlayer (void) //Bot���܂߂�player�̐�
226 {
227 	int i,j;
228 	edict_t *ent;
229 
230 	j = 0;
231 	for (i=0 ; i<maxclients->value ; i++)
232 	{
233 		ent = g_edicts + 1 + i;
234 		if (ent->inuse)	j++;
235 	}
236 	return j;
237 }
238 
239 //----------------------------------------------------------------
240 //Get New Client
241 //
242 // Get new client edict
243 //
244 //----------------------------------------------------------------
245 
Get_NewClient(void)246 edict_t *Get_NewClient (void)
247 {
248 	int			i;
249 	edict_t		*e;
250 	gclient_t	*client;
251 
252 	e = &g_edicts[(int)maxclients->value];
253 	for ( i = maxclients->value ; i >= 1  ; i--, e--)
254 	{
255 		client = &game.clients[i - 1];
256 		// the first couple seconds of server time can involve a lot of
257 		// freeing and allocating, so relax the replacement policy
258 		if (!e->inuse && !client->pers.connected && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) )
259 		{
260 			G_InitEdict (e);
261 			return e;
262 		}
263 	}
264 	gi.error ("ED_Alloc: no free edicts shit");
265 	return NULL;
266 }
267 
268 
269 //----------------------------------------------------------------
270 //Bot Think
271 //
272 // Bot's think code
273 //
274 //----------------------------------------------------------------
Bot_Think(edict_t * self)275 void Bot_Think (edict_t *self)
276 {
277 	gclient_t	*client;
278 
279 	if (self->linkcount != self->monsterinfo.linkcount)
280 	{
281 //		self->monsterinfo.linkcount = self->linkcount;
282 		M_CheckGround (self);
283 	}
284 
285 	if(self->deadflag)
286 	{
287 		if(self->client->ctf_grapple) CTFPlayerResetGrapple(self);
288 
289 		if(self->s.modelindex == skullindex || self->s.modelindex == headindex) self->s.frame = 0;
290 		else if(self->s.frame < FRAME_crdeath1 && self->s.frame != 0) self->s.frame = FRAME_death308;
291 		self->s.modelindex2 = 0;	// remove linked weapon model
292 //ZOID
293 		self->s.modelindex3 = 0;	// remove linked ctf flag
294 //ZOID
295 
296 		self->client->zc.route_trace = false;
297 		if(self->client->respawn_time <= level.time)
298 		{
299 			if(self->svflags & SVF_MONSTER)
300 			{
301 				self->client->respawn_time = level.time;
302 				CopyToBodyQue (self);
303 				PutBotInServer(self);
304 			}
305 		}
306 	}
307 	else
308 	{
309 		Bots_Move_NORM (self);
310 		if(!self->inuse) return;			//removed botself
311 
312 		client = self->client;
313 
314 		ClientBeginServerFrame (self);
315 	}
316 	if (self->linkcount != self->monsterinfo.linkcount)
317 	{
318 //		self->monsterinfo.linkcount = self->linkcount;
319 		M_CheckGround (self);
320 	}
321 	M_CatagorizePosition (self);
322 	BotEndServerFrame (self);
323 	self->nextthink = level.time + FRAMETIME;
324 	return;
325 }
326 
327 //----------------------------------------------------------------
328 //Initialize Bot
329 //
330 // Initialize bot edict
331 //
332 //----------------------------------------------------------------
333 
InitializeBot(edict_t * ent,int botindex)334 void InitializeBot (edict_t *ent,int botindex )
335 {
336 	gclient_t	*client;
337 	char		pinfo[200];
338 	int			index;
339 
340 	index = ent-g_edicts-1;
341 	ent->client = &game.clients[index];
342 
343 	client = ent->client;
344 
345 	memset (&client->zc,0,sizeof(zgcl_t));
346 	memset (&client->pers, 0, sizeof(client->pers));
347 	memset (&client->resp, 0, sizeof(client->resp));
348 
349 	//set botindex NO.
350 	client->zc.botindex = botindex;
351 
352 	client->resp.enterframe = level.framenum;
353 
354 	//set netname model skil and CTF team
355 	sprintf(pinfo,"\\rate\\25000\\msg\\1\\fov\\90\\skin\\%s/%s\\name\\%s\\hand\\0",Bot[botindex].model,Bot[botindex].skin,Bot[botindex].netname);
356 	ent->client->resp.ctf_team = Bot[botindex].team; //CTF_TEAM1,CTF_TEAM2
357 
358 	ClientUserinfoChanged (ent, pinfo);
359 
360 	client->pers.health			= 100;
361 	client->pers.max_health		= 100;
362 
363 	client->pers.max_bullets	= 200;
364 	client->pers.max_shells		= 100;
365 	client->pers.max_rockets	= 50;
366 	client->pers.max_grenades	= 50;
367 	client->pers.max_cells		= 200;
368 	client->pers.max_slugs		= 50;
369 
370 	// RAFAEL
371 	client->pers.max_magslug	= 50;
372 	client->pers.max_trap		= 5;
373 
374 	ent->client->pers.connected = false;
375 	gi.dprintf ("%s connected\n", ent->client->pers.netname);
376 //	gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
377 
378 	if(ctf->value)	gi.bprintf(PRINT_HIGH, "%s joined the %s team.\n",
379 			client->pers.netname, CTFTeamName(ent->client->resp.ctf_team));
380 	else 	gi.bprintf (PRINT_HIGH, "%s entered the game\n",
381 			client->pers.netname);
382 }
383 
PutBotInServer(edict_t * ent)384 void PutBotInServer (edict_t *ent)
385 {
386 	edict_t		*touch[MAX_EDICTS];
387 	int			i,j,entcount;
388 	gitem_t		*item;
389 	gclient_t	*client;
390 	vec3_t	spawn_origin, spawn_angles;
391 	trace_t		rs_trace;
392 
393 
394 	zgcl_t		*zc;
395 
396 	zc = &ent->client->zc;
397 
398 //test
399 //	item = FindItem("Trap");
400 //	ent->client->pers.inventory[ITEM_INDEX(item)] = 100;
401 //test
402 
403 	//current weapon
404 	client = ent->client;
405 	item = Fdi_BLASTER;//FindItem("Blaster");
406 	client->pers.selected_item = ITEM_INDEX(item);
407 	client->pers.inventory[client->pers.selected_item] = 1;
408 	client->pers.weapon = item;
409 	client->silencer_shots = 0;
410 	client->weaponstate = WEAPON_READY;
411 	client->newweapon = NULL;
412 
413 	//clear powerups
414 	client->quad_framenum = 0;
415 	client->invincible_framenum = 0;
416 	client->breather_framenum = 0;
417 	client->enviro_framenum = 0;
418 	client->grenade_blew_up = false;
419 	client->grenade_time = 0;
420 
421 	j = zc->botindex;
422 	i = zc->routeindex;
423 	memset (&client->zc,0,sizeof(zgcl_t));
424 	zc->botindex = j;
425 	zc->routeindex = i;
426 
427 //ZOID
428 	client->ctf_grapple = NULL;
429 
430 	item = FindItem("Grapple");
431 	if(ctf->value)	client->pers.inventory[ITEM_INDEX(item)] = 1; //ponpoko
432 //ZOID
433 
434 	// clear entity values
435 	ent->classname = "player";
436 	ent->movetype = MOVETYPE_STEP;
437 	ent->solid = SOLID_BBOX;
438 	ent->model = "players/male/tris.md2";
439 	VectorSet (ent->mins, -16, -16, -24);
440 	VectorSet (ent->maxs, 16, 16, 32);
441 
442 	ent->health = ent->client->pers.health;
443 	ent->max_health = ent->client->pers.max_health;
444 	ent->gib_health = -40;
445 
446 	ent->mass = 200;
447 	ent->target_ent = NULL;
448 	ent->s.frame = 0;
449 
450 	// clear entity state values
451 	ent->s.modelindex = 255;		// will use the skin specified model
452 	ent->s.skinnum = ent - g_edicts - 1;
453 	ShowGun(ent);					// ### Hentai ### special gun model
454 
455 	ent->s.sound = 0;
456 
457 	ent->monsterinfo.scale = MODEL_SCALE;
458 
459 	ent->pain = player_pain;
460 	ent->die = player_die;
461 	ent->touch = NULL;
462 
463 	ent->moveinfo.decel = level.time;
464 	ent->pain_debounce_time = level.time;
465 	ent->targetname = NULL;
466 
467 	ent->moveinfo.speed = 1.0;	//�W�����v���̈ړ����ɂ‚��Ēlj�
468 	ent->moveinfo.state = GETTER;	//CTF�X�e�[�^�X������
469 
470 	ent->prethink = NULL;
471 	ent->think = Bot_Think;
472 	ent->nextthink = level.time + FRAMETIME;
473 	ent->svflags /*|*/= SVF_MONSTER ;
474 	ent->s.renderfx = 0;
475 	ent->s.effects = 0;
476 
477 	SelectSpawnPoint (ent, spawn_origin, spawn_angles);
478 	VectorCopy (spawn_origin, ent->s.origin);
479 	VectorCopy (spawn_angles, ent->s.angles);
480 	spawn_origin[2] -= 300;
481 	rs_trace = gi.trace(ent->s.origin,ent->mins,ent->maxs,spawn_origin,ent,MASK_SOLID);
482 	if(!rs_trace.allsolid) VectorCopy (rs_trace.endpos, ent->s.origin);
483 	VectorSet(ent->velocity,0,0,0);
484 	ent->moveinfo.speed = 0;
485 	ent->groundentity = rs_trace.ent;
486 	ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
487 
488 	Set_BotAnim(ent,ANIM_BASIC,FRAME_run1,FRAME_run6);
489 	client->anim_run = true;
490 
491 	ent->client->ctf_grapple = NULL;
492 	ent->client->quad_framenum = level.framenum;
493 	ent->client->invincible_framenum = level.framenum;
494 	ent->client->enviro_framenum = level.framenum;
495 	ent->client->breather_framenum = level.framenum;
496 	ent->client->weaponstate = WEAPON_READY;
497 	ent->takedamage = DAMAGE_AIM;
498 	ent->air_finished = level.time + 12;
499 	ent->clipmask = MASK_PLAYERSOLID;//MASK_MONSTERSOLID;
500 	ent->flags &= ~FL_NO_KNOCKBACK;
501 
502 	ent->client->anim_priority = ANIM_BASIC;
503 //	ent->client->anim_run = true;
504 	ent->s.frame = FRAME_run1-1;
505 	ent->client->anim_end = FRAME_run6;
506 	ent->deadflag = DEAD_NO;
507 	ent->svflags &= ~SVF_DEADMONSTER;
508 
509 	zc->waitin_obj = NULL;
510 	zc->first_target = NULL;
511 	zc->first_target = NULL;
512 	zc->zcstate = STS_IDLE;
513 
514 	if(ent->client->resp.enterframe == level.framenum && !chedit->value)
515 	{
516 		gi.WriteByte (svc_muzzleflash);
517 		gi.WriteShort (ent-g_edicts);
518 		gi.WriteByte (MZ_LOGIN);
519 		gi.multicast (ent->s.origin, MULTICAST_PVS);
520 	}
521 	else if(!chedit->value)
522 	{
523 		gi.WriteByte (svc_muzzleflash);
524 		gi.WriteShort (ent-g_edicts);
525 		gi.WriteByte (MZ_RESPAWN);
526 		gi.multicast (ent->s.origin, MULTICAST_PVS);
527 	}
528 	gi.linkentity (ent);
529 	VectorAdd (spawn_origin, ent->mins, ent->absmin);
530 	VectorAdd (spawn_origin, ent->maxs, ent->absmax);
531 	entcount = gi.BoxEdicts ( ent->absmin ,ent->absmax,touch,MAX_EDICTS,AREA_SOLID);
532 	while (entcount-- > 0)
533 	{
534 		if(Q_stricmp (touch[entcount]->classname, "player") == 0)
535 			if(touch[entcount] != ent)
536 				T_Damage (touch[entcount], ent, ent, vec3_origin, touch[entcount]->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
537 	}
538 
539 	if(ctf->value)
540 	{
541 		CTFPlayerResetGrapple(ent);
542 		client->zc.ctfstate = CTFS_OFFENCER;
543 	}
544 
545 
546 	gi.linkentity (ent);
547 	G_TouchTriggers (ent);
548 }
549 
550 //----------------------------------------------------------------
551 //Spawn Bot
552 //
553 // spawn bots
554 //
555 //	int i	index of bot list
556 //
557 //----------------------------------------------------------------
558 
SpawnBot(int i)559 qboolean SpawnBot(int i)
560 {
561 	edict_t		*bot,*ent;
562 	int			k,j;
563 
564 
565 //gi.cprintf (NULL,PRINT_HIGH,"Called %s %s %s\n",Bot[i].netname,Bot[i].model,Bot[i].skin);
566 //return false;
567 
568 	if(	Get_NumOfPlayer () >= game.maxclients )
569 	{
570 		gi.cprintf (NULL,PRINT_HIGH,"Can't add bots\n");
571 		return false;
572 	}
573 
574 	bot = Get_NewClient();
575 	if(bot == NULL) return false;
576 
577 	InitializeBot( bot , i);
578 	PutBotInServer ( bot );
579 
580 	j = targetindex;
581 	if(chedit->value)
582 	{
583 		for(k = CurrentIndex - 1;k > 0 ;k--)
584 		{
585 			if(Route[k].index == 0) break;
586 
587 			if(Route[k].state == GRS_NORMAL)
588 			{
589 				if(--j <= 0) break;
590 			}
591 		}
592 
593 		bot->client->zc.rt_locktime = level.time + FRAMETIME * 20;
594 		bot->client->zc.route_trace = true;
595 		bot->client->zc.routeindex = k;
596 		VectorCopy(Route[k].Pt,bot->s.origin);
597 		VectorAdd (bot->s.origin, bot->mins, bot->absmin);
598 		VectorAdd (bot->s.origin, bot->maxs, bot->absmax);
599 		bot->client->ps.pmove.pm_flags |= PMF_DUCKED;
600 		gi.linkentity (bot);
601 //		bot->s.modelindex = 0;
602 
603 		gi.WriteByte (svc_muzzleflash);
604 		gi.WriteShort (bot-g_edicts);
605 		gi.WriteByte (MZ_LOGIN);
606 		gi.multicast (bot->s.origin, MULTICAST_PVS);
607 
608 		ent = &g_edicts[1];
609 		if(ent->inuse && ent->client && !(ent->svflags & SVF_MONSTER))
610 		{
611 			ent->takedamage = DAMAGE_NO;
612 			ent->movetype = MOVETYPE_NOCLIP;
613 			ent->target_ent = bot;
614 			ent->solid = SOLID_NOT;
615 			ent->client->ps.pmove.pm_type = PM_FREEZE;
616 			ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION ;
617 			VectorCopy(ent->s.origin,ent->moveinfo.start_origin);
618 		}
619 	}
620 
621 	return true;
622 }
623 
624 //----------------------------------------------------------------
625 //Spawn Call
626 //
627 // spawn bots
628 //
629 //	int i	index of bot list
630 //
631 //----------------------------------------------------------------
Bot_SpawnCall()632 void Bot_SpawnCall()
633 {
634 	int i;
635 
636 	for(i = 0;i < MAXBOTS;i++)
637 	{
638 		if(Bot[i].spflg == BOT_SPRESERVED)
639 		{
640 			if(SpawnBot(i)) Bot[i].spflg = BOT_SPAWNED;
641 			else
642 			{
643 				Bot[i].spflg = BOT_SPAWNNOT;
644 				targetindex = 0;
645 			}
646 			SpawnWaitingBots--;
647 			break;
648 		}
649 	}
650 }
651 //----------------------------------------------------------------
652 //Spawn Bot Reserving
653 //
654 // spawn bots reserving
655 //
656 //----------------------------------------------------------------
SpawnBotReserving()657 void SpawnBotReserving()
658 {
659 	int	i;
660 
661 	for(i = 0;i < MAXBOTS; i++)
662 	{
663 		if(Bot[i].spflg == BOT_SPAWNNOT)
664 		{
665 			Bot[i].spflg = BOT_SPRESERVED;
666 			SpawnWaitingBots++;
667 			return;
668 		}
669 	}
670 	gi.cprintf (NULL, PRINT_HIGH, "Now max of bots(%i) already spawned.\n",MAXBOTS);
671 }
672 //----------------------------------------------------------------
673 //Spawn Bot Reserving 2
674 //
675 // randomized spawn bots reserving
676 //
677 //----------------------------------------------------------------
SpawnBotReserving2(int * red,int * blue)678 void SpawnBotReserving2(int *red,int *blue)
679 {
680 	int	i,j;
681 
682 	j = (int)(random() * ListedBots);
683 
684 	for(i = 0;i < ListedBots; i++,j++)
685 	{
686 		if(j >= ListedBots) j = 0;
687 		if(Bot[j].spflg == BOT_SPAWNNOT)
688 		{
689 			Bot[j].spflg = BOT_SPRESERVED;
690 			SpawnWaitingBots++;
691 			if(*red > *blue) Bot[j].team = 2;
692 			else Bot[j].team = 1;
693 
694 			if(Bot[j].team == 1) *red = *red + 1;
695 			else if(Bot[j].team == 2) *blue = *blue + 1;
696 //gi.cprintf(NULL,PRINT_HIGH,"team %i\n",Bot[j].team);
697 			return;
698 		}
699 	}
700 	SpawnBotReserving();
701 }
702 
703 //----------------------------------------------------------------
704 //Remove Bot
705 //
706 // remove bots
707 //
708 //	int i	index of bot list
709 //
710 //----------------------------------------------------------------
RemoveBot()711 void RemoveBot()
712 {
713 	int			i;
714 	int			botindex;
715 	edict_t		*e,*ent;
716 	gclient_t	*client;
717 
718 	for(i = MAXBOTS - 1;i >= 0;i--)
719 	{
720 		if(Bot[i].spflg == BOT_SPAWNED || Bot[i].spflg == BOT_NEXTLEVEL)
721 		{
722 			break;
723 		}
724 	}
725 
726 	if(i < 0)
727 	{
728 		gi.cprintf (NULL, PRINT_HIGH, "No Bots in server.");
729 		return;
730 	}
731 
732 	botindex = i;
733 
734 	e = &g_edicts[(int)maxclients->value];
735 	for ( i = maxclients->value ; i >= 1  ; i--, e--)
736 	{
737 		if(!e->inuse) continue;
738 		client = /*e->client;*/&game.clients[i - 1];
739 		if(client == NULL) continue;
740 		// the first couple seconds of server time can involve a lot of
741 		// freeing and allocating, so relax the replacement policy
742 		if (!client->pers.connected && (e->svflags & SVF_MONSTER))
743 		{
744 			if(client->zc.botindex == botindex)
745 			{
746 				if(Bot[botindex].spflg != BOT_NEXTLEVEL) Bot[botindex].spflg = BOT_SPAWNNOT;
747 				else Bot[botindex].spflg = BOT_SPRESERVED;
748 
749 				gi.bprintf (PRINT_HIGH, "%s disconnected\n", e->client->pers.netname);
750 
751 				// send effect
752 				gi.WriteByte (svc_muzzleflash);
753 				gi.WriteShort (e-g_edicts);
754 				gi.WriteByte (MZ_LOGOUT);
755 				gi.multicast (e->s.origin, MULTICAST_PVS);
756 
757 				e->s.modelindex = 0;
758 				e->solid = SOLID_NOT;
759 
760 	if(ctf->value) CTFPlayerResetGrapple(e);
761 
762 				gi.linkentity (e);
763 
764 				e->inuse = false;
765 				G_FreeEdict (e);
766 
767 				if(targetindex)
768 				{
769 					ent = &g_edicts[1];
770 
771 					if(ent->inuse)
772 					{
773 						ent->health = 100;
774 						ent->movetype = MOVETYPE_WALK;
775 						ent->takedamage = DAMAGE_AIM;
776 						ent->target_ent = NULL;
777 						ent->solid = SOLID_BBOX;
778 						ent->client->ps.pmove.pm_type = PM_NORMAL;
779 						ent->client->ps.pmove.pm_flags = PMF_DUCKED;
780 						VectorCopy(ent->moveinfo.start_origin,ent->s.origin);
781 						VectorCopy(ent->moveinfo.start_origin,ent->s.old_origin);
782 					}
783 					targetindex = 0;
784 				}
785 				return;
786 			}
787 		}
788 	}
789 	gi.error ("Can't remove bot.");
790 }
791 
792 //----------------------------------------------------------------
793 //Level Change Removing
794 //
795 //
796 //
797 //----------------------------------------------------------------
Bot_LevelChange()798 void Bot_LevelChange()
799 {
800 	int i,j,k;
801 
802 	j = 0,k = 0;
803 
804 	for(i = 0;i < MAXBOTS;i++)
805 	{
806 		if(Bot[i].spflg)
807 		{
808 			if(Bot[i].spflg == BOT_SPAWNED)
809 			{
810 				k++;
811 				Bot[i].spflg = BOT_NEXTLEVEL;
812 			}
813 			j++;
814 		}
815 	}
816 	for(i = 0;i < k; i++)
817 	{
818 		RemoveBot();
819 	}
820 
821 	SpawnWaitingBots = k;//j;
822 }
823 //----------------------------------------------------------------
824 //
825 //	Ragomode menu
826 //
ZigockClientJoin(edict_t * ent,int zclass)827 void ZigockClientJoin(edict_t  *ent,int zclass)
828 {
829 	PMenu_Close(ent);
830 
831 	ent->moveinfo.sound_end = CLS_ALPHA;	//PutClient�̑O�ɃN���X����
832 
833 	ent->svflags &= ~SVF_NOCLIENT;
834 	PutClientInServer (ent);
835 	// add a teleportation effect
836 	ent->s.event = EV_PLAYER_TELEPORT;
837 	// hold in place briefly
838 	ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
839 	ent->client->ps.pmove.pm_time = 14;
840 
841 	if(ctf->value)
842 	{
843 		gi.bprintf(PRINT_HIGH, "%s joined the %s team.\n",
844 			ent->client->pers.netname, CTFTeamName(ent->client->resp.ctf_team/*desired_team*/));
845 	}
846 }
ClientJoinAsAlpha(edict_t * ent,pmenu_t * entries)847 void ClientJoinAsAlpha(edict_t *ent,pmenu_t *entries)
848 {
849 	ZigockClientJoin(ent,1);
850 }
851 
852 pmenu_t zgjoinmenu[] = {
853 	{ "*Quake II",			PMENU_ALIGN_CENTER, NULL, NULL },
854 	{ "*3rd Zigock Rago",	PMENU_ALIGN_CENTER, NULL, NULL },
855 	{ NULL,					PMENU_ALIGN_CENTER, NULL, NULL },
856 	{ NULL,					PMENU_ALIGN_CENTER, NULL, NULL },
857 	{ "alpha",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
858 	{ "beta",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
859 	{ "gamma",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
860 	{ "delta",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
861 	{ "epsilon",			PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
862 	{ "zeta",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
863 	{ "eta",				PMENU_ALIGN_LEFT, NULL, ClientJoinAsAlpha },
864 	{ NULL,					PMENU_ALIGN_LEFT, NULL, NULL },
865 	{ "Use [ and ] to move cursor",	PMENU_ALIGN_LEFT, NULL, NULL },
866 	{ "ENTER to select class",	PMENU_ALIGN_LEFT, NULL, NULL },
867 	{ "ESC to Exit Menu",	PMENU_ALIGN_LEFT, NULL, NULL },
868 	{ "(TAB to Return)",	PMENU_ALIGN_LEFT, NULL, NULL },
869 };
870 
ZigockJoinMenu(edict_t * ent)871 void ZigockJoinMenu(edict_t *ent)
872 {
873 	PMenu_Open(ent, zgjoinmenu,4, sizeof(zgjoinmenu) / sizeof(pmenu_t));
874 }
875 
ZigockStartClient(edict_t * ent)876 qboolean ZigockStartClient(edict_t *ent)
877 {
878 	if (ent->moveinfo.sound_end != CLS_NONE)
879 		return false;
880 
881 	// start as 'observer'
882 	ent->movetype = MOVETYPE_NOCLIP;
883 	ent->solid = SOLID_NOT;
884 	ent->svflags |= SVF_NOCLIENT;
885 	ent->client->ps.gunindex = 0;
886 	gi.linkentity (ent);
887 
888 	ZigockJoinMenu(ent);
889 	return true;
890 }
891 
892 
893 //===============================
894 
895 //	AirStrike
896 
897 //===============================
AirSight_Explode(edict_t * ent)898 static void AirSight_Explode (edict_t *ent)
899 {
900 	vec3_t		origin;
901 	int			mod;
902 
903 //	if (ent->owner->client && !(ent->owner->svflags & SVF_DEADMONSTER))
904 //		PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
905 
906 	gi.sound (ent, CHAN_AUTO, gi.soundindex("3zb/airexp.wav"), 1, ATTN_NONE, 0);
907 
908 	//FIXME: if we are onground then raise our Z just a bit since we are a point?
909 	mod = MOD_AIRSTRIKE;
910 
911 	T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod);
912 
913 	VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
914 	gi.WriteByte (svc_temp_entity);
915 	if (ent->waterlevel)
916 	{
917 		gi.WriteByte (TE_ROCKET_EXPLOSION_WATER);
918 	}
919 	else
920 	{
921 		gi.WriteByte (TE_ROCKET_EXPLOSION);
922 	}
923 	gi.WritePosition (origin);
924 	gi.multicast (ent->s.origin, MULTICAST_PHS);
925 
926 	G_FreeEdict (ent);
927 }
928 
AirSight_Think(edict_t * ent)929 void AirSight_Think(edict_t *ent)
930 {
931 //	gi.sound (ent, CHAN_AUTO, gi.soundindex("medic/medatck1.wav"), 1, ATTN_NORM, 0);
932 	gi.sound (ent, CHAN_BODY, gi.soundindex("3zb/airloc.wav"), 1, ATTN_NONE, 0);
933 
934 	ent->dmg = 120 + random() * 60;
935 	ent->dmg_radius = 200;
936 
937 	ent->s.modelindex = gi.modelindex ("sprites/airsight.sp2");
938 	VectorCopy(ent->target_ent->s.origin,ent->s.origin);
939 
940 	if( ent->owner->client->resp.ctf_team == CTF_TEAM2 && ctf->value)
941 	{
942 		ent->s.frame = 1;
943 	}
944 	else ent->s.frame = 0;
945 
946 	ent->think = AirSight_Explode;
947 	ent->nextthink = level.time + FRAMETIME * 6;
948 	gi.linkentity (ent);
949 }
AirStrike_Think(edict_t * ent)950 void AirStrike_Think(edict_t *ent)
951 {
952 	int	i,j;
953 	edict_t	*target,*sight;
954 	trace_t	rs_trace;
955 
956 	vec3_t	point;
957 
958 	ent->nextthink = level.time + ent->moveinfo.speed * 0.5 /300;
959 	ent->think = G_FreeEdict;
960 //	ent->s.modelindex = gi.modelindex ("models/ships/bigviper/tris.md2");
961 
962 	VectorCopy(ent->s.origin,point);
963 	point[2] = ent->moveinfo.start_angles[2];
964 
965 	j = 1;
966 	for ( i = 1 ; i <= maxclients->value; i++)
967 	{
968 		target =  &g_edicts[i];
969 		if(!target->inuse || target->deadflag || target == ent->owner) continue;
970 
971 		if( target->classname[0] == 'p')
972 		{
973 			//ctf �Ȃ�`�[�����C�g����
974 			if(!ctf->value || (ctf->value && ent->owner->client->resp.ctf_team != target->client->resp.ctf_team))
975 			{
976 				rs_trace = gi.trace (point,NULL,NULL,target->s.origin,ent, CONTENTS_SOLID | CONTENTS_WINDOW | CONTENTS_LAVA | CONTENTS_SLIME);
977 
978 				if(rs_trace.fraction == 1.0)
979 				{
980 					sight = G_Spawn();
981 
982 					sight->classname = "airstrike";
983 					sight->think = AirSight_Think;
984 					sight->nextthink = level.time + FRAMETIME * 2 * (float)j;
985 					sight->movetype = MOVETYPE_NOCLIP;
986 					sight->solid = SOLID_NOT;
987 					sight->owner = ent->owner;
988 					sight->target_ent = target;
989 					gi.linkentity (sight);
990 					j++;
991 				}
992 			}
993 		}
994 	}
995 
996 }
Cmd_AirStrike(edict_t * ent)997 void Cmd_AirStrike(edict_t *ent)
998 {
999 	edict_t	*viper;
1000 	trace_t	rs_trace;
1001 
1002 	vec3_t	strpoint,tts,tte,tmp;
1003 
1004 	vec_t	f;
1005 
1006 	VectorCopy(ent->s.origin,strpoint);
1007 	strpoint[2] += 8190;
1008 
1009 	rs_trace = gi.trace (ent->s.origin,NULL,NULL,strpoint,ent, MASK_SHOT);
1010 
1011 	if(!(rs_trace.surface && (rs_trace.surface->flags & SURF_SKY)))
1012 	{
1013 		gi.cprintf(ent,PRINT_HIGH,"can't call Viper.\n");
1014 		return;
1015 	}
1016 /*	if((rs_trace.endpos[2] - ent->s.origin[2]) < 300)
1017 	{
1018 		gi.cprintf(ent,PRINT_HIGH,"can't call Viper.\n");
1019 	}*/
1020 
1021 	VectorCopy(rs_trace.endpos,strpoint);
1022 	strpoint[2] -= 16;	//������Ƃ������ւ��炷
1023 
1024 	f = ent->s.angles[YAW]*M_PI*2 / 360;
1025 	tts[0] = cos(f) * (-8190) ;
1026 	tts[1] = sin(f) * (-8190) ;
1027 	tts[2] = 0;
1028 
1029 	tte[0] = cos(f) *8190 ;
1030 	tte[1] = sin(f) *8190 ;
1031 	tte[2] = 0;
1032 
1033 	viper = G_Spawn();
1034 	VectorClear (viper->mins);
1035 	VectorClear (viper->maxs);
1036 	viper->movetype = /*MOVETYPE_FLYMISSILE;//MOVETYPE_STEP;*/MOVETYPE_NOCLIP;
1037 	viper->solid = SOLID_NOT;
1038 	viper->owner = ent;
1039 	viper->s.modelindex = gi.modelindex ("models/ships/viper/tris.md2");
1040 
1041 	VectorCopy(ent->s.angles,viper->s.angles);
1042 	viper->s.angles[2] = 0;
1043 	rs_trace = gi.trace (strpoint,NULL,NULL,tts,ent,  MASK_SHOT);
1044 	tts[0] = cos(f) * (-600) ;
1045 	tts[1] = sin(f) * (-600) ;
1046 	VectorAdd(rs_trace.endpos,tts,tmp);
1047 	VectorCopy(tmp,viper->s.origin);
1048 
1049 
1050 	viper->velocity[0] = cos(f) * 300;
1051 	viper->velocity[1] = sin(f) * 300;
1052 	viper->velocity[2] = 0;
1053 
1054 	rs_trace = gi.trace (strpoint,NULL,NULL,tte,ent,  MASK_SHOT);
1055 	VectorSubtract(viper->s.origin,rs_trace.endpos,tts);
1056 	f = VectorLength(tts);
1057 
1058 	gi.sound (viper, CHAN_AUTO, gi.soundindex("world/flyby1.wav"), 1, ATTN_NONE, 0);
1059 
1060 	gi.sound (ent, CHAN_AUTO, gi.soundindex("world/incoming.wav"), 1, ATTN_NONE, 0);
1061 
1062 	viper->nextthink = level.time + f *0.75 /300;
1063 	viper->think = AirStrike_Think;
1064 	viper->moveinfo.speed = f;
1065 
1066 //	viper->s.sound = gi.soundindex ("weapons/rockfly.wav");
1067 
1068 	//	viper->s.effects |= EF_ROTATE | EF_COLOR_SHELL;
1069 //	viper->s.renderfx |= RF_SHELL_BLUE | RF_SHELL_GREEN;
1070 	VectorCopy(strpoint,viper->moveinfo.start_angles);	//strikepoint
1071 
1072 //	viper->think = Pod_think;
1073 //	viper->nextthink = level.time + FRAMETIME;
1074 	viper->classname = "viper";
1075 	viper->s.origin[2] += 16;
1076 	gi.linkentity (viper);
1077 }
1078 
1079