/*
	DooM 64 INFO.c processor, by Frans P. de Vries.

Derived from:

	DooM MaP StaTistics, by Frans P. de Vries.

	You are allowed to use any parts of this code in another program, as
	long as you give credits to the authors in the documentation and in
	the program itself.  Read the file README for more information.

	This program comes with absolutely no warranty.

	PRINT.C - Print routines.
*/

#include "../common/print.h"
#include "../common/things.h"
#include "../common/maps.h"
#include "../common/stub.h"
#include "doomdef.h"
#include "sounds.h"


/*
	the global variables
*/
extern int maxammo[];
extern int clipammo[];

/*
	the local function prototypes
*/
void PrintSound(char *, int);
void PrintWpnAmmo( weapontype_t);
void PrintShotsPM( mobjinfo_t *);
void PrintWpnShotsPM( weapontype_t);
void PrintWpnSprites( weapontype_t);


/*
	the weapon print data function
*/
void PrintWeapon()
{
	if (Weap < 0 || Weap >= NUMWEAPONS)
		ProgError( "no such Weapon %d", Weap);

	if (XWik)
	{
		tpldata = TMPL_add_var( tpldata, "NAME", Wpn2Str( Weap), NULL);
		memset(fieldlist, 0, LISTSIZE);
		memset(field2list, 0, LISTSIZE);
	}
	else
	{
		printf( "\n");
		printf( "Weapon\t\t%s\n", Wpn2Str( Weap));
	}
	PrintWpnAmmo( Weap);
	PrintWpnShotsPM( Weap);
	if (!XWik)
		printf( "\n");
	PrintWpnSprites( Weap);

	if (XWik)
	{
		tpldata = TMPL_add_var( tpldata, "STATELIST", fieldlist, NULL);
		if (weaponthing[Weap] != -1)
		{
			Thng = weaponthing[Weap];
			PrintData();
		}
	}
	else
		PrintSpawns();
}

/*
	the main print data function
*/
void PrintData()
{
	mobjinfo_t *MOBJ;

	if (Enum != NULL)
		Objt = Enum2Obj( Enum);
	else if (Thng != -1)
		Objt = Thg2Obj( Thng);
	else
		if (Objt < 0 || Objt >= NUMMOBJTYPES)
			ProgError( "no such Object %d", Objt);

	MOBJ = &mobjinfo[Objt];
	PrintTypeHealth( MOBJ);

	if (MOBJ->flags & MF_SPECIAL) // pick-up item
		PrintShotsPM( MOBJ);
	else
		PrintSpeed( MOBJ);

	PrintDimsTimesFlags( MOBJ);

	TallyFrames( MOBJ->spawnstate, FALSE);
	TallyFrames( MOBJ->seestate, FALSE);
	TallyFrames( MOBJ->painstate, FALSE);
	TallyFrames( MOBJ->meleestate, FALSE);
	TallyFrames( MOBJ->missilestate, FALSE);
	TallyFrames( MOBJ->deathstate, FALSE);
	TallyFrames( MOBJ->xdeathstate, FALSE);

	if (XWik)
	{
		memset(fieldlist, 0, LISTSIZE);
		memset(field2list, 0, LISTSIZE);
	}
	else
		printf( "\n");
	if (MOBJ->flags & MF_SPECIAL) // pick-up item
	{
		PrintItemSprites( MOBJ);
	}
	else
	{
		if (MOBJ->doomednum != -1 && LookupThingClass( MOBJ->doomednum) == ThClassMnst ||
		    Objt == MT_PLAYER || Objt == MT_PLAYERBOT1 ||
		    Objt == MT_PLAYERBOT2 || Objt == MT_PLAYERBOT3)
			PrintMonsterSprites( MOBJ);
		else
		{
			PrintSprite( MOBJ->spawnstate, ST_NONE, FALSE);
			if (XWik)
			{
				tpldata = TMPL_add_var( tpldata, "SPRITE", fieldlist, NULL);
				tpldata = TMPL_add_var( tpldata, "FRAMES", field2list, NULL);
				memset(fieldlist, 0, LISTSIZE);
				memset(field2list, 0, LISTSIZE);
			}
			PrintSprite( MOBJ->deathstate, ST_NONE, FALSE);
			if (XWik)
			{
				tpldata = TMPL_add_var( tpldata, "SPRITE2", fieldlist, NULL);
				tpldata = TMPL_add_var( tpldata, "FRAMES2", field2list, NULL);
			}
		}

		PrintSound( "Alert",  MOBJ->seesound);
		PrintSound( "Active", MOBJ->activesound);
		PrintSound( "Attack", MOBJ->attacksound);
		PrintSound( "Pain",   MOBJ->painsound);
		PrintSound( "Death",  MOBJ->deathsound);
	}
	PrintSpawns();
}


void PrintSound(char *type, int sound)
{
	char type2[8];

	// cannot run strupr on static param
	strcpy( type2, type);
	strupr( type2);
	if (!XWik)
		printf( "%s sound\t", type);
	if (sound != 0)
	{
		if (XWik)
			tpldata = TMPL_add_var( tpldata, type2, S_sfx[sound].name, NULL);
		else
			printf( "%s\n", S_sfx[sound].name);
	}
	else
	{
		if (XWik)
			tpldata = TMPL_add_var( tpldata, type2, "-", NULL);
		else
			printf( "-\n");
	}
}

void PrintWpnAmmo( weapontype_t weapon)
{
	int ammo;

	ammo = clipammo[weaponinfo[weapon].ammo];
	if (XWik)
	{
		tmpl_add_int( tpldata, "INCAMMO", "%d", ammo * 2);
		tmpl_add_int( tpldata, "INCAMM2", "%d", ammo * 2 * 2); // 2 clips
	}
	else
		printf("Incl ammo\t%d (%d on [[Skill level|skills]] 1 & 5)\n", ammo * 2, ammo * 2 * 2); // 2 clips

	ammo = maxammo[weaponinfo[weapon].ammo];
	if (XWik)
	{
		tmpl_add_int( tpldata, "MAXAMMO", "%d", ammo);
		tmpl_add_int( tpldata, "BPKAMMO", "%d", ammo * 2);
		tpldata = TMPL_add_var( tpldata, "BACKPACK", "backpack", NULL);
	}
	else
		printf("Max ammo\t%d (%d with [[backpack]])\n", ammo, ammo * 2);
}


void PrintShotsPM( mobjinfo_t *MOBJ)
{
	int weapon;

	switch (states[MOBJ->spawnstate].sprite)
	{
		case SPR_CSAW: weapon = wp_chainsaw; break;
		case SPR_SHOT: weapon = wp_shotgun; break;
		case SPR_SGN2: weapon = wp_supershotgun; break;
		case SPR_MGUN: weapon = wp_chaingun; break;
		case SPR_LAUN: weapon = wp_missile; break;
		case SPR_PLAS: weapon = wp_plasma; break;
		case SPR_BFUG: weapon = wp_bfg; break;
		default: return;
	}
	PrintWpnShotsPM( weapon);
}

void PrintWpnShotsPM( weapontype_t weapon)
{
	int percycle = 0, tics = 0;
	statenum_t state, st;

	state = st = weaponinfo[weapon].atkstate;
	if (state != S_000)
		for (;;)
		{
			if (states[st].action)
				states[st].action(NULL);
			else
				funcname[0] = '\0';
			if (strncmp( funcname, "A_Fire", strlen("A_Fire")) == 0 ||
			    strcmp( funcname, "A_Punch") == 0 ||
			    strcmp( funcname, "A_Saw") == 0)
				percycle++;
			else if (strcmp( funcname, "A_ReFire") == 0)
				break;
			tics += states[st].tics;
			st = states[st].nextstate;
			if (tics > 100)
				ProgError( "unable to count tics for atkstate %d", state);
		}

	if (tics != 0)
		if (XWik)
			tmpl_add_float( tpldata, "SHOTMIN", "%.1f",
			                (float)percycle * (TICRATE * 60) / tics);
		else
			printf( "Shots / min\t%.1f\n",
			        (float)percycle * (TICRATE * 60) / tics);
}

int FrameTics( statenum_t state)
{
	statenum_t st = state;

	/* skip Arachnotron sight state */
	if (!states[st].action)
		st = states[st].nextstate;

	/* skip to A_Chase state */
	if (states[st].action)
		states[st].action(NULL);
	else
		funcname[0] = '\0';
	if (strcmp( funcname, "A_Hoof") == 0 ||     // Cyberdemon
	    strcmp( funcname, "A_Metal") == 0 ||    // Spiderdemon
	    strcmp( funcname, "A_BabyMetal") == 0)  // Arachnotron
		st = states[st].nextstate;

	if (states[st].action)
	{
		states[st].action(NULL);
		if (strcmp( funcname, "A_Chase") == 0 ||    // generic
		    strcmp( funcname, "A_RectChase") == 0)  // Mother Demon
			return states[st].tics;
	}

	return -1;
}


void PrintItemSprites( mobjinfo_t *MOBJ)
{
	int weapon;

	switch (states[MOBJ->spawnstate].sprite)
	{
		case SPR_CSAW: weapon = wp_chainsaw; break;
		case SPR_SHOT: weapon = wp_shotgun; break;
		case SPR_SGN2: weapon = wp_supershotgun; break;
		case SPR_MGUN: weapon = wp_chaingun; break;
		case SPR_LAUN: weapon = wp_missile; break;
		case SPR_PLSM: weapon = wp_plasma; break;
		case SPR_BFUG: weapon = wp_bfg; break;
		case SPR_LSRG: weapon = wp_laser; break;
		default:
			PrintSprite( MOBJ->spawnstate, ST_NONE, FALSE);
			tpldata = TMPL_add_var( tpldata, "SPRITE", fieldlist, NULL);
			tpldata = TMPL_add_var( tpldata, "FRAMES", field2list, NULL);
			return;
	}
	PrintSprite( MOBJ->spawnstate, ST_PICKUP, FALSE);
	PrintWpnSprites( weapon);

	tpldata = TMPL_add_var( tpldata, "STATELIST", fieldlist, NULL);
}

void PrintWpnSprites( weapontype_t weapon)
{
	PrintSprite( weaponinfo[weapon].readystate, ST_WIELD, FALSE);
	PrintSprite( weaponinfo[weapon].atkstate, ST_FIRE, TRUE);
	PrintSprite( weaponinfo[weapon].atkstate, ST_REFIRE, FALSE);
	PrintSprite( weaponinfo[weapon].flashstate, ST_FLASH, FALSE);
}

void PrintMonsterSprites( mobjinfo_t *MOBJ)
{
	memset(fieldlist, 0, LISTSIZE);
	PrintSprite( MOBJ->spawnstate, ST_NONE, FALSE);
	tpldata = TMPL_add_var( tpldata, "SPRITE", fieldlist, NULL);

	memset(fieldlist, 0, LISTSIZE);
	PrintSprite( MOBJ->spawnstate, ST_SPAWN, FALSE);
	PrintSprite( MOBJ->seestate, ST_SEE, FALSE);
	PrintSprite( MOBJ->meleestate, ST_MELEE, FALSE);
	PrintSprite( MOBJ->missilestate, ST_MISSL, FALSE);
	PrintSprite( MOBJ->painstate, ST_PAIN, FALSE);
	PrintSprite( MOBJ->deathstate, ST_DEATH, FALSE);
	PrintSprite( MOBJ->xdeathstate, ST_XDEATH, FALSE);
	tpldata = TMPL_add_var( tpldata, "STATELIST", fieldlist, NULL);
}

/* vim:set noexpandtab tabstop=2 softtabstop=2 shiftwidth=2: */
