shithub: choc

ref: ded5e702b8f28f9eb2d5322d47f0cd08e93cb74b
dir: /src/strife/p_dialog.c/

View raw version
// 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;
}