shithub: qk2

ref: a4c4b45d8b2136733c76a4b86c7896bfa939ad25
dir: qk2/crbot/cr_menu.c

View raw version
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include "../dat.h"
#include "../fns.h"

void SP_crbot( char* name, int skill_level, char* skin, int team, char* model );
void cr_show_stats( edict_t *self );

#define MENU_MAIN     1
#define MENU_ADD_BOT  2

#define MI_MAIN_ADDBOT      1
#define MI_MAIN_STATS       2
#define MI_MAIN_TEAMS       3
#define MI_MAIN_MYTEAM      4
#define MI_MAIN_OBITUARY    5
#define MI_MAIN_BOTCHAT     6
#define MI_MAIN_TAUNT       7
#define MI_MAIN_MAPCYCLE    8
#define MI_MAIN_TECHS       9
#define MI_MAIN_HOOK        10
#define MI_MAIN_SAVENODES   11
#define MI_MAIN_MAX         11

#define MI_AB_PREVMENU   1
#define MI_AB_SKILL      2
#define MI_AB_MODEL      3
#define MI_AB_SKIN       4
#define MI_AB_TEAM       5 
#define MI_AB_ADDBOT     6
#define MI_AB_MAX        6

#define MAX_SKIN  1024
#define MAX_MODEL 128

typedef char stname[32];

stname skins[MAX_SKIN], models[MAX_MODEL];
int    nmodel=0, curmd=0, curskin=0;
int    skhead[MAX_MODEL], nskin[MAX_MODEL];

void cr_invert_string( char* pc )
{
	while(*pc!='"') {
		*pc |= 0x80;
		pc++;
	}
}

/* FIXME: bullshit */
void cr_menu_init(void)
{
	char mdir[256], sdir[512], *p;
	int fd, nmd, nsk, mdi, sdi, l, n, s_count, s_start = 0;
	Dir *md = nil, *sk = nil;

	memset(skins, 0, sizeof skins);
	memset(models, 0, sizeof models);
	seprint(mdir, mdir+sizeof mdir, "%s/baseq2/players", base_path->string);

	if((fd = open(mdir, OREAD)) < 0){
		fprint(2, "cr_menu_init:open: %r\n");
		goto fail;
	}
	nmd = dirreadall(fd, &md);
	close(fd);
	if(nmd <= 0){
		fprint(2, "cr_menu_init:dirreadall: %r\n");
		goto fail;
	}
	if(nmd > MAX_MODEL){
		fprint(2, "cr_menu_init: too many models\n");
		goto fail;
	}

	/* get models and skins */
	nmodel = 0;
	for(mdi=0; mdi < nmd; mdi++){
		/* [words]
			return thisdir->d_name[0] != '.';
			//return thisdir->d_type == DT_DIR; //always returns zero ?
		*/
		if(~md[mdi].mode & DMDIR)
			continue;

		strncpy(models[nmodel], md[mdi].name, sizeof *models);
		seprint(sdir, sdir+sizeof sdir, "%s/%s", mdir, models[nmodel]);
		if((fd = open(sdir, OREAD)) < 0){
			fprint(2, "cr_menu_init:open: %r\n");
			goto fail;
		}
		nsk = dirreadall(fd, &sk);
		close(fd);
		if(nsk <= 0){
			fprint(2, "cr_menu_init:dirreadall: %r\n");
			continue;
		}

		s_count = 0;
		for(sdi = 0; sdi < nsk; sdi++){
			if(strstr(sk[sdi].name, "_i.pcx") == nil)
				continue;
			p = skins[s_start+s_count];
			memset(p, 0, sizeof *p);
			l = strlen(sk[sdi].name) - 6;
			if(l > sizeof *p)
				l = sizeof *p;
			strncpy(p, sk[sdi].name, l);
			s_count++;
		}
		free(sk);
		skhead[nmodel] = s_start;
		nskin[nmodel] = s_count;
		s_start += s_count;
		nmodel++;
	}
	free(md);

	for(n=0; n < nmodel; n++)
		if(!cistrcmp(bot_model->string, models[n])){
			curmd = n;
			break;
		}
	for(n=0; n < nskin[curmd]; n++)
		if(!cistrcmp(bot_skin->string, skins[skhead[curmd]+n])){
			curskin = n;
			break;
		}
	gi.cvar_forceset("bot_model", models[curmd]);
	gi.cvar_forceset("bot_skin", skins[skhead[curmd]+curskin]);
	return;
fail:
	free(md);
	free(sk);
	gi.error("failed to init models and skins");
}

void cr_menu_draw( edict_t *self )
{
	char  menu[1400], *pch;
	gclient_t *cl;

	cl = self->client;
	if (!cl || self->bot_info) return;

	if (cl->menu_no<=0) cl->menu_no=1;
	if (cl->menu_item_no<=0) cl->menu_item_no=0;

	pch = menu;
	sprintf ( pch, "xv 32 yv 8 picn inventory " );
	pch += strlen(pch);

	switch (cl->menu_no) {
	case MENU_MAIN:
		sprintf( pch, "xv 0 yv 30 cstring2 \"[CRBot] main menu:\" "
			"xv 0 yv 32 cstring2 \"__________________\" " );
		break;
	case MENU_ADD_BOT:
		sprintf( pch, "xv 0 yv 30 cstring2 \"[CRBot] add new bot:\" "
			"xv 0 yv 32 cstring2 \"____________________\" " );
		break;
	default:
		cl->menu_no=0;
		return;
	};
	pch += strlen(pch);

	switch (cl->menu_no) {
	case MENU_MAIN:
		sprintf( pch, "xv 56 yv 50 string2 \"add new bot...\" " );
		if (cl->menu_item_no!=MI_MAIN_ADDBOT) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 60 string2 \"show bots statistics...\" " );
		if (cl->menu_item_no!=MI_MAIN_STATS) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 70 string2 \"show team scores...\" " );
		if (cl->menu_item_no!=MI_MAIN_TEAMS) cr_invert_string(pch+21);
		pch += strlen(pch);
		if (self->client->pers.team_no)
			sprintf( pch, "xv 56 yv 80 string2 \"player's team     = %d\" ", self->client->pers.team_no );
		else
			sprintf( pch, "xv 56 yv 80 string2 \"player's team     = none\" " );
		if (cl->menu_item_no!=MI_MAIN_MYTEAM) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 90 string2 \"obituary messages = %s\" ", obituary_msgs->value ? "show" : "skip" );
		if (cl->menu_item_no!=MI_MAIN_OBITUARY) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 100 string2 \"bot chat          = %s\" ", bot_chat->value ? "on" : "off" );
		if (cl->menu_item_no!=MI_MAIN_BOTCHAT) cr_invert_string(pch+22);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 110 string2 \"bot taunts        = %s\" ", bot_taunt->value ? "on" : "off" );
		if (cl->menu_item_no!=MI_MAIN_TAUNT) cr_invert_string(pch+22);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 120 string2 \"map cycle         = %s\" ", ((int)map_cycle->value)==2 ? "random" : ((int)map_cycle->value)==1 ? "on" : "off" );
		if (cl->menu_item_no!=MI_MAIN_MAPCYCLE) cr_invert_string(pch+22);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 130 string2 \"techs in dm game  = %s\" ", !((int)no_tech->value) ? "enable" : "disable" );
		if (cl->menu_item_no!=MI_MAIN_TECHS) cr_invert_string(pch+22);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 140 string2 \"g.hook in dm game = %s\" ", !((int)no_hook->value) ? "enable" : "disable" );
		if (cl->menu_item_no!=MI_MAIN_HOOK) cr_invert_string(pch+22);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 150 string2 \"save nodemap file...\" " );
		if (cl->menu_item_no!=MI_MAIN_SAVENODES) cr_invert_string(pch+22);
		break;
	case MENU_ADD_BOT:
		sprintf( pch, "xv 56 yv 50 string2 \"...back to main menu...\" " );
		if (cl->menu_item_no!=MI_AB_PREVMENU) cr_invert_string(pch+21);
		pch += strlen(pch);
		if (bot_skill->value)
			sprintf( pch, "xv 56 yv 60 string2 \"skill  = %d\" ", (int)bot_skill->value );
		else
			sprintf( pch, "xv 56 yv 60 string2 \"skill  = adapting\" " );
		if (cl->menu_item_no!=MI_AB_SKILL) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 70 string2 \"model   = %s\" ", bot_model->string );
		if (cl->menu_item_no!=MI_AB_MODEL) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 80 string2 \"skin    = %s\" ", bot_skin->string );
		if (cl->menu_item_no!=MI_AB_SKIN) cr_invert_string(pch+21);
		pch += strlen(pch);
		if (bot_team->value)
			sprintf( pch, "xv 56 yv 90 string2 \"team    = %d\" ", (int)bot_team->value );
		else
			sprintf( pch, "xv 56 yv 90 string2 \"team    = none\" " );
		if (cl->menu_item_no!=MI_AB_TEAM) cr_invert_string(pch+21);
		pch += strlen(pch);
		sprintf( pch, "xv 56 yv 100 string2 \"-> add new bot <-\" " );
		if (cl->menu_item_no!=MI_AB_ADDBOT) cr_invert_string(pch+22);
		break;
	};

	gi.configstring ( CS_STATUSBAR, menu );
}


void cr_menu_select( edict_t *self, int ds )
{
	gclient_t *cl;
	int        no;
	char       buf[8];

	cl = self->client;
	if (!cl || self->bot_info) return;

	switch (cl->menu_no) {
	case MENU_MAIN:
		switch (cl->menu_item_no) {
		case MI_MAIN_ADDBOT:
			cl->menu_no = MENU_ADD_BOT;
			cl->menu_item_no = 1;
			break;
		case MI_MAIN_OBITUARY:
			gi.cvar_forceset( "obituary_msgs", obituary_msgs->value ? "0" : "1" );
			break;
		case MI_MAIN_MYTEAM:
			self->client->pers.team_no += ds;
			if (self->client->pers.team_no>10) self->client->pers.team_no=0;
			if (self->client->pers.team_no<0) self->client->pers.team_no=10;
			break;
		case MI_MAIN_STATS:
			cr_show_stats(self);
			break;
		case MI_MAIN_TEAMS:
			cr_show_team_stats(self);
			break;
		case MI_MAIN_BOTCHAT:
			gi.cvar_forceset( "bot_chat", bot_chat->value ? "0" : "1" );
			break;
		case MI_MAIN_TAUNT:
			gi.cvar_forceset( "bot_taunt", bot_taunt->value ? "0" : "1" );
			break;
		case MI_MAIN_MAPCYCLE:
			gi.cvar_forceset( "map_cycle", va( "%d", ((int)map_cycle->value+ds+3)%3 ) );
			break;
		case MI_MAIN_TECHS:
			gi.cvar_forceset( "no_tech", no_tech->value ? "0" : "1" );
			break;
		case MI_MAIN_HOOK:
			gi.cvar_forceset( "no_hook", no_hook->value ? "0" : "1" );
			break;
		case MI_MAIN_SAVENODES:
			cr_routes_save(self);
			break;
		}
		break;

	case MENU_ADD_BOT:
		switch (cl->menu_item_no) {
		case MI_AB_PREVMENU:
			cl->menu_no = MENU_MAIN;
			cl->menu_item_no = 1;
			break;
		case MI_AB_MODEL:
			curmd+=ds;
			if (curmd>=nmodel) curmd=0;
			if (curmd<0) curmd=nmodel-1;
			gi.cvar_forceset( "bot_model", models[curmd] );
			if (curskin>=nskin[curmd])
				curskin = nskin[curmd]-1;
			gi.cvar_forceset( "bot_skin", skins[skhead[curmd]+curskin] );
			break;
		case MI_AB_SKIN:
			if (curmd>=nmodel) curmd=nmodel-1;
			curskin+=ds;
			if (curskin>=nskin[curmd]) curskin=0;
			if (curskin<0) curskin = nskin[curmd]-1;
			gi.cvar_forceset( "bot_skin", skins[skhead[curmd]+curskin] );
			break;
		case MI_AB_TEAM:
			no = ((int)bot_team->value + ds + 10) % 10;
			sprintf(buf,"%d",no);
			gi.cvar_forceset( "bot_team", buf );
			break;
		case MI_AB_SKILL:
			no = ((int)bot_skill->value + ds + 10) % 10;
			sprintf(buf,"%d",no);
			gi.cvar_forceset( "bot_skill", buf );
			break;
		case MI_AB_ADDBOT:
			SP_crbot( NULL, bot_skill->value, bot_skin->string, bot_team->value, bot_model->string );
			break;
		}
		break;
	}

	cr_menu_draw(self);
}

void cr_menu_up( edict_t *self )
{
	gclient_t *cl;

	cl = self->client;
	if (!cl || self->bot_info) return;

	cl->menu_item_no--;
	if (cl->menu_item_no<=0)
		switch (cl->menu_no) {
		case MENU_MAIN:
			cl->menu_item_no=MI_MAIN_MAX;
			break;
		case MENU_ADD_BOT:
			cl->menu_item_no=MI_AB_MAX;
			break;
		default:
			cl->menu_item_no=1;
		}

	cr_menu_draw(self);
}

void cr_menu_down( edict_t *self )
{
	gclient_t *cl;

	cl = self->client;
	if (!cl || self->bot_info) return;

	cl->menu_item_no++;
	switch (cl->menu_no) {
	case MENU_MAIN:
		if (cl->menu_item_no>MI_MAIN_MAX) cl->menu_item_no=1;
		break;
	case MENU_ADD_BOT:
		if (cl->menu_item_no>MI_AB_MAX) cl->menu_item_no=1;
		break;
	default:
		cl->menu_item_no=1;
	}

	cr_menu_draw(self);
}