ref: ab0dc8fcb49a71db33e26f9c01e88d24e43c556e
dir: /src/strife/p_dialog.c/
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 1996 Rogue Entertainment / Velocity, Inc.
// Copyright(C) 2010 James Haley, Samuel Villareal
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// DESCRIPTION:
//
// [STRIFE] New Module
//
// Dialog Engine for Strife
//
//-----------------------------------------------------------------------------
#include "z_zone.h"
#include "w_wad.h"
#include "deh_str.h"
#include "d_player.h"
#include "doomstat.h"
#include "p_dialog.h"
//
// Defines and Macros
//
// haleyjd: size of the original Strife mapdialog_t structure.
#define ORIG_MAPDIALOG_SIZE 0x5EC
//
// Static Globals
//
// True if SCRIPT00 is loaded.
static boolean script0loaded;
// Number of dialogs defined in the current level's script.
static int numleveldialogs;
// The actual level dialogs. This didn't exist in Strife, but is new to account
// for structure alignment/packing concerns, given that Chocolate Doom is
// multiplatform.
static mapdialog_t *leveldialogs;
// The actual script00 dialogs. As above.
static mapdialog_t *script0dialogs;
// Number of dialogs defined in the SCRIPT00 lump.
static int numscript0dialogs;
//
// Routines
//
#define DIALOG_INT(field, ptr) \
field = ((int)ptr[0] | \
((int)ptr[1] << 8) | \
((int)ptr[2] << 16) | \
((int)ptr[3] << 24)); \
ptr += 4;
#define DIALOG_STR(field, ptr, len) \
memcpy(field, ptr, len); \
ptr += len;
//
// P_ParseDialogLump
//
// haleyjd 09/02/10: This is a new function added to parse out the dialogs
// from the dialog lump rather than reading them raw from the lump pointer.
// This avoids problems with structure packing.
//
static void P_ParseDialogLump(byte *lump, mapdialog_t **dialogs,
int numdialogs, int tag)
{
int i;
byte *rover = lump;
*dialogs = Z_Malloc(numdialogs * sizeof(mapdialog_t), tag, NULL);
for(i = 0; i < numdialogs; i++)
{
int j;
mapdialog_t *curdialog = &((*dialogs)[i]);
DIALOG_INT(curdialog->speakerid, rover);
DIALOG_INT(curdialog->dropitem, rover);
DIALOG_INT(curdialog->checkitem1, rover);
DIALOG_INT(curdialog->checkitem2, rover);
DIALOG_INT(curdialog->checkitem3, rover);
DIALOG_INT(curdialog->jumptoconv, rover);
DIALOG_STR(curdialog->name, rover, MDLG_NAMELEN);
DIALOG_STR(curdialog->voice, rover, MDLG_LUMPLEN);
DIALOG_STR(curdialog->backpic, rover, MDLG_LUMPLEN);
DIALOG_STR(curdialog->text, rover, MDLG_TEXTLEN);
// copy choices
for(j = 0; j < 5; j++)
{
mapdlgchoice_t *curchoice = &(curdialog->choices[j]);
DIALOG_INT(curchoice->giveitem, rover);
DIALOG_INT(curchoice->needitem1, rover);
DIALOG_INT(curchoice->needitem2, rover);
DIALOG_INT(curchoice->needitem3, rover);
DIALOG_INT(curchoice->needamount1, rover);
DIALOG_INT(curchoice->needamount2, rover);
DIALOG_INT(curchoice->needamount3, rover);
DIALOG_STR(curchoice->text, rover, MDLG_CHOICELEN);
DIALOG_STR(curchoice->textok, rover, MDLG_MSGLEN);
DIALOG_INT(curchoice->next, rover);
DIALOG_INT(curchoice->objective, rover);
DIALOG_STR(curchoice->textno, rover, MDLG_MSGLEN);
}
}
}
//
// P_DialogLoad
//
// [STRIFE] New function
// haleyjd 09/02/10: Loads the dialog script for the current map. Also loads
// SCRIPT00 if it has not yet been loaded.
//
void P_DialogLoad(int eax0, int a2, int a3, int a4)
{
char lumpname[9];
int lumpnum;
// load the SCRIPTxy lump corresponding to MAPxy, if it exists.
sprintf(lumpname, DEH_String("script%02d"), gamemap);
if((lumpnum = W_CheckNumForName(lumpname)) == -1)
numleveldialogs = 0;
else
{
byte *leveldialogptr = W_CacheLumpNum(lumpnum, PU_STATIC);
numleveldialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE;
P_ParseDialogLump(leveldialogptr, &leveldialogs, numleveldialogs,
PU_LEVEL);
Z_Free(leveldialogptr); // haleyjd: free the original lump
}
// also load SCRIPT00 if it has not been loaded yet
if(!script0loaded)
{
byte *script0ptr;
script0loaded = true;
// BUG: Rogue should have used W_GetNumForName here...
lumpnum = W_CheckNumForName(DEH_String("script00"));
script0ptr = W_CacheLumpNum(lumpnum, PU_STATIC);
numscript0dialogs = W_LumpLength(lumpnum) / ORIG_MAPDIALOG_SIZE;
P_ParseDialogLump(script0ptr, &script0dialogs, numscript0dialogs,
PU_STATIC);
Z_Free(script0ptr); // haleyjd: free the original lump
}
}
//
// P_PlayerHasItem
//
// [STRIFE] New function
// haleyjd 09/02/10: Checks for inventory items, quest flags, etc. for dialogs.
// Returns the amount possessed, or 0 if none.
//
int P_PlayerHasItem(player_t *player, mobjtype_t type)
{
int i;
if(type > 0)
{
// check keys
if(type >= MT_KEY_BASE && type < MT_INV_SHADOWARMOR)
return (player->cards[type - MT_KEY_BASE]);
// check sigil pieces
if(type >= MT_SIGIL_A && type <= MT_SIGIL_E)
return (type - MT_SIGIL_A <= player->sigiltype);
// check quest tokens
if(type >= MT_TOKEN_QUEST1 && type <= MT_TOKEN_QUEST31)
return (player->questflags & (1 << (type - MT_TOKEN_QUEST1)));
// check inventory
for(i = 0; i < 32; i++)
{
if(type == player->inventory[i].type)
return player->inventory[i].amount;
}
}
return 0;
}