Source release of Wolfenstein 3D Classic Platinum for iOS, 1.1

This commit is contained in:
Travis Bradshaw
2012-01-31 16:55:36 -06:00
parent e20e553baf
commit a82aba6b94
421 changed files with 68803 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,968 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2001 by DarkOne the Hacker
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.
*/
/*
* wolf_actor_ai.c: Wolfenstein3-D artificial intelligence.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
const char dsounds[ 7 ][ 32 ] =
{
"sfx/025.wav",
"sfx/026.wav",
"sfx/086.wav",
"sfx/088.wav",
"sfx/105.wav",
"sfx/107.wav",
"sfx/109.wav"
};
const char dsodsounds[ 7 ][ 32 ] =
{
"sfx/021.wav",
"sfx/022.wav",
"sfx/052.wav",
"sfx/054.wav",
"sfx/057.wav",
"sfx/059.wav",
"sfx/061.wav"
};
/*
-----------------------------------------------------------------------------
Function: A_DeathScream() -Do a death scream sound depending on actor type.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_DeathScream( entity_t *self )
{
switch( self->type )
{
case en_mutant:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/033.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/037.wav" ), 1, ATTN_NORM, 0 );
}
break;
case en_guard:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( dsodsounds[ US_RndT() % 6 ] ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( dsounds[ US_RndT() % 6 ] ), 1, ATTN_NORM, 0 );
}
break;
case en_officer:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/046.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/074.wav" ), 1, ATTN_NORM, 0 );
}
break;
case en_ss:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/035.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/046.wav" ), 1, ATTN_NORM, 0 );
}
break;
case en_dog:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/031.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/035.wav" ), 1, ATTN_NORM, 0 );
}
break;
case en_boss:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/019.wav" ), 1, ATTN_NORM, 0 );
break;
case en_schabbs:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/061.wav" ), 1, ATTN_NORM, 0 );
break;
case en_fake:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/069.wav" ), 1, ATTN_NORM, 0 );
break;
case en_mecha:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/084.wav" ), 1, ATTN_NORM, 0 );
break;
case en_hitler:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/044.wav" ), 1, ATTN_NORM, 0 );
break;
case en_gretel:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/115.wav" ), 1, ATTN_NORM, 0 );
break;
case en_gift:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/091.wav" ), 1, ATTN_NORM, 0 );
break;
case en_fat:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/119.wav" ), 1, ATTN_NORM, 0 );
break;
case en_spectre:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "lsfx/062.wav" ), 1, ATTN_NORM, 0 );
break;
case en_angel:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/098.wav" ), 1, ATTN_NORM, 0 );
break;
case en_trans:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/070.wav" ), 1, ATTN_NORM, 0 );
break;
case en_uber:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/082.wav" ), 1, ATTN_NORM, 0 );
break;
case en_will:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/072.wav" ), 1, ATTN_NORM, 0 );
break;
case en_death:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/090.wav" ), 1, ATTN_NORM, 0 );
break;
}
}
/*
-----------------------------------------------------------------------------
Function: A_FirstSighting() -Puts an actor into attack mode and possibly
reverses the direction if the player is
behind it.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_FirstSighting( entity_t *self )
{
switch( self->type )
{
case en_guard:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/001.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_officer:
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/043.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/071.wav" ), 1, ATTN_NORM, 0 );
}
self->speed *= 5; // go faster when chasing player
break;
case en_mutant:
self->speed *= 3; // go faster when chasing player
break;
case en_ss:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/015.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 4; // go faster when chasing player
break;
case en_dog:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/002.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 2; // go faster when chasing player
break;
case en_boss:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/017.wav" ), 1, ATTN_NORM, 0 );
self->speed = SPDPATROL * 3; // go faster when chasing player
break;
case en_gretel:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/112.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_gift:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/096.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_fat:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/102.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_schabbs:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/065.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_fake:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/054.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_mecha:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/040.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 3; // go faster when chasing player
break;
case en_hitler:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/040.wav" ), 1, ATTN_NORM, 0 );
self->speed *= 5; // go faster when chasing player
break;
case en_blinky:
case en_clyde:
case en_pinky:
case en_inky:
self->speed *= 2; // go faster when chasing player
break;
//
// Spear of Destiny
//
case en_spectre:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "lsfx/003.wav" ), 1, ATTN_NORM, 0 );
self->speed = 800; // go faster when chasing player
break;
case en_angel:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/095.wav" ), 1, ATTN_NORM, 0 );
self->speed = 1536; // go faster when chasing player
break;
case en_trans:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/066.wav" ), 1, ATTN_NORM, 0 );
self->speed = 1536; // go faster when chasing player
break;
case en_uber:
self->speed = 3000; // go faster when chasing player
break;
case en_will:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/073.wav" ), 1, ATTN_NORM, 0 );
self->speed = 2048; // go faster when chasing player
break;
case en_death:
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/085.wav" ), 1, ATTN_NORM, 0 );
self->speed = 2048; // go faster when chasing player
break;
default:
return;
}
A_StateChange( self, st_chase1 );
if( self->waitfordoorx )
{
self->waitfordoorx = self->waitfordoory = 0; // ignore the door opening command
}
self->dir = dir8_nodir;
self->flags |= FL_ATTACKMODE | FL_FIRSTATTACK;
}
/*
-----------------------------------------------------------------------------
Function: A_KillActor() -Actor has been killed, so give points and spawn
powerups.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void A_KillActor( entity_t *self )
{
int tilex, tiley;
tilex = self->tilex = self->x >> TILESHIFT; // drop item on center
tiley = self->tiley = self->y >> TILESHIFT;
switch( self->type )
{
case en_guard:
PL_GivePoints( &Player, 100 );
Powerup_Spawn( tilex, tiley, pow_clip2 );
break;
case en_officer:
PL_GivePoints( &Player, 400 );
Powerup_Spawn( tilex, tiley, pow_clip2 );
break;
case en_mutant:
PL_GivePoints( &Player, 700 );
Powerup_Spawn( tilex, tiley, pow_clip2 );
break;
case en_ss:
PL_GivePoints( &Player, 500 );
if( Player.items & ITEM_WEAPON_3 ) // have a schmeiser?
{
Powerup_Spawn( tilex, tiley, pow_clip2 );
}
else
{
Powerup_Spawn( tilex, tiley, pow_machinegun );
}
break;
case en_dog:
PL_GivePoints( &Player, 200 );
break;
case en_boss:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
case en_gretel:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
case en_gift:
PL_GivePoints( &Player, 5000 );
A_StartDeathCam( self );
break;
case en_fat:
PL_GivePoints( &Player, 5000 );
A_StartDeathCam( self );
break;
case en_schabbs:
PL_GivePoints( &Player, 5000 );
A_DeathScream( self );
A_StartDeathCam( self );
break;
case en_fake:
PL_GivePoints( &Player, 2000 );
break;
case en_mecha:
PL_GivePoints( &Player, 5000 );
break;
case en_hitler:
PL_GivePoints( &Player, 5000 );
A_DeathScream( self );
A_StartDeathCam( self );
break;
case en_spectre:
PL_GivePoints( &Player, 200 );
break;
case en_angel:
PL_GivePoints( &Player, 5000 );
break;
case en_trans:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
case en_uber:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
case en_will:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
case en_death:
PL_GivePoints( &Player, 5000 );
Powerup_Spawn( tilex, tiley, pow_key1 );
break;
}
A_StateChange( self, st_die1 );
if ( ++levelstate.killed_monsters == levelstate.total_monsters ) {
iphoneSetNotifyText( "You killed the last enemy!" );
}
self->flags &= ~FL_SHOOTABLE;
self->flags |= FL_NONMARK;
}
/*
-----------------------------------------------------------------------------
Function: A_DamageActor() -Called when the player succesfully hits an enemy.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
Does damage points to enemy ob, either putting it into a stun frame or
killing it.
-----------------------------------------------------------------------------
*/
PUBLIC void A_DamageActor( entity_t *self, int damage )
{
Player.madenoise = 1;
// do double damage if shooting a non attack mode actor
if( ! (self->flags & FL_ATTACKMODE) )
{
damage <<= 1;
}
self->health -= damage;
if( self->health <= 0 )
{
A_KillActor( self );
}
else
{
if( ! (self->flags & FL_ATTACKMODE) )
{
A_FirstSighting( self ); // put into combat mode
}
switch( self->type ) // dogs only have one hit point
{
case en_guard:
case en_officer:
case en_mutant:
case en_ss:
if( self->health & 1 )
{
A_StateChange( self, st_pain );
}
else
{
A_StateChange( self, st_pain1 );
}
break;
}
}
}
///////////////////////////
//
// Hitler
//
///////////////////////////
/*
-----------------------------------------------------------------------------
Function: A_MechaSound -Play Mecha sound.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_MechaSound( entity_t *self )
{
if( areabyplayer[ self->areanumber ] )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "sfx/080.wav" ), 1, ATTN_NORM, 0 );
}
}
/*
-----------------------------------------------------------------------------
Function: A_Slurpie -Play Slurpie sound.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Slurpie( entity_t *self )
{
Sound_StartSound( NULL, 1, CHAN_VOICE, Sound_RegisterSound( "lsfx/061.wav" ), 1, ATTN_NORM, 0 );
}
/*
-----------------------------------------------------------------------------
Function: A_HitlerMorph() -Spawn new actor, when Mecha Hitler is dead.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_HitlerMorph( entity_t *self )
{
int hitpoints[ 4 ] = { 500, 700, 800, 900 };
entity_t *hitler;
hitler = GetNewActor();
if( ! hitler )
{
return;
}
hitler->x = self->x;//
hitler->y = self->y;//
hitler->distance = self->distance;
hitler->tilex = self->tilex;//
hitler->tiley = self->tiley;//
hitler->angle = self->angle;//
hitler->dir = self->dir;//
hitler->health = hitpoints[ (int)skill->value ];
hitler->areanumber = self->areanumber;
hitler->state = st_chase1;//
hitler->type = en_hitler; //
hitler->speed = SPDPATROL * 5;//
hitler->ticcount = 0;//
hitler->flags=self->flags | FL_SHOOTABLE; //
hitler->sprite = Sprite_GetNewSprite();
if ( ++levelstate.killed_monsters == levelstate.total_monsters ) {
iphoneSetNotifyText( "You killed the last enemy!" );
}
}
///////////////////////////
//
// Angel of Death
//
///////////////////////////
/*
Angel can't shoot more then 3 sparks in a row.
It will get tired!
*/
PRIVATE int angel_temp = 0;
//
/*
-----------------------------------------------------------------------------
Function: A_Breathing -Play Angel of Death Breathing sound.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Breathing( entity_t *self )
{
Sound_StartSound( NULL, 0, CHAN_VOICE, Sound_RegisterSound( "lsfx/080.wav" ), 1, ATTN_NORM, 0 );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_StartAttack( entity_t *self )
{
angel_temp = 0;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Relaunch( entity_t *self )
{
if( ++angel_temp == 3 )
{
A_StateChange( self, st_pain );
return;
}
if( US_RndT() & 1 )
{
A_StateChange( self, st_chase1 );
return;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Victory( entity_t *self )
{
iphoneStartIntermission( 0 );
}
/*
-----------------------------------------------------------------------------
Function: A_Dormant() -Entity is dormant state.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Dormant( entity_t *self )
{
int deltax, deltay;
int xl, xh, yl, yh, x, y, n;
deltax = self->x - Player.position.origin[ 0 ];
if( deltax < -MINACTORDIST || deltax > MINACTORDIST )
{
goto moveok;
}
deltay = self->y - Player.position.origin[ 1 ];
if( deltay < -MINACTORDIST || deltay > MINACTORDIST )
{
goto moveok;
}
return;
moveok:
xl = (self->x - MINDIST) >> TILESHIFT;
xh = (self->x + MINDIST) >> TILESHIFT;
yl = (self->y - MINDIST) >> TILESHIFT;
yh = (self->y + MINDIST) >> TILESHIFT;
for( y = yl ; y <= yh ; ++y )
for( x = xl ; x <= xh ; ++x )
{
if( r_world->tilemap[ x ][ y ] & SOLID_TILE )
{
return;
}
for( n = 0 ; n < NumGuards ; ++n )
{
if( Guards[ n ].state >= st_die1 )
{
continue;
}
if( Guards[ n ].tilex == x && Guards[ n ].tiley == y )
{
return; // another guard in path
}
}
}
self->flags |= FL_AMBUSH | FL_SHOOTABLE;
self->flags &= ~FL_ATTACKMODE;
self->dir = dir8_nodir;
A_StateChange( self, st_path1 );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_StartDeathCam( entity_t *self )
{
// the DeathCam feature isn't implimented, but we want to give the animation time
// to play before declaring victory.
iphoneStartIntermission( 50 );
}
/*
-----------------------------------------------------------------------------
Function: A_Smoke() -Rockets emmit smoke.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_Smoke( entity_t *self )
{
entity_t *smoke;
smoke = GetNewActor();
if( ! smoke )
{
return;
}
smoke->x = self->x;
smoke->y = self->y;
smoke->tilex = self->tilex;
smoke->tiley = self->tiley;
smoke->state = st_die1;
smoke->type = (self->type==en_hrocket) ? en_hsmoke : en_smoke;
smoke->ticcount = 6;
smoke->flags = FL_NEVERMARK;
smoke->sprite = Sprite_GetNewSprite();
}
/*
-----------------------------------------------------------------------------
Function: ProjectileTryMove() -Called when projectile is airborne.
Parameters: self -[in] Valid Pointer to an entity_t structure.
lvl -[in] Valid Pointer to LevelData_t structure.
Returns: true if move ok, otherwise false.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE _boolean ProjectileTryMove( entity_t *self, LevelData_t *lvl )
{
#define PROJSIZE 0x2000
int xl, yl, xh, yh, x, y;
xl = (self->x - PROJSIZE) >> TILESHIFT;
yl = (self->y - PROJSIZE) >> TILESHIFT;
xh = (self->x + PROJSIZE) >> TILESHIFT;
yh = (self->y + PROJSIZE) >> TILESHIFT;
// Checking for solid walls:
for( y = yl ; y <= yh ; ++y )
{
for( x = xl ; x <= xh ; ++x )
{
// FIXME: decide what to do with statics & Doors!
if( lvl->tilemap[ x ][ y ] & (WALL_TILE | BLOCK_TILE) )
{
return false;
}
if( lvl->tilemap[ x ][ y ] & DOOR_TILE )
{
if( Door_Opened( &lvl->Doors, x, y ) != DOOR_FULLOPEN )
{
return false;
}
}
}
}
// FIXME: Projectile will fly through objects (even guards & columns) - must fix to create rocket launcher!
return true;
}
/*
-----------------------------------------------------------------------------
Function: T_Projectile() -Called when projectile is airborne.
Parameters: self -[in] Valid Pointer to an entity_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void T_Projectile( entity_t *self )
{
#define PROJECTILESIZE 0xC000
int deltax, deltay, speed, damage;
speed = self->speed * tics;
deltax = (int)(speed * CosTable[ self->angle ]);
deltay = (int)(speed * SinTable[ self->angle ]);
if( deltax > TILEGLOBAL )
{
deltax = TILEGLOBAL;
}
if( deltax < -TILEGLOBAL )
{
deltax = -TILEGLOBAL; // my
}
if( deltay > TILEGLOBAL)
{
deltay = TILEGLOBAL;
}
if( deltay < -TILEGLOBAL)
{
deltay = -TILEGLOBAL; // my
}
self->x += deltax;
self->y += deltay;
deltax = ABS( self->x-Player.position.origin[ 0 ] );
deltay = ABS( self->y-Player.position.origin[ 1 ] );
if( ! ProjectileTryMove( self, r_world ) )
{
if( self->type == en_rocket || self->type == en_hrocket )
{ // rocket ran into obstacle, draw explosion!
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_WEAPON, Sound_RegisterSound( "lsfx/001.wav" ), 1, ATTN_NORM, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_WEAPON, Sound_RegisterSound( "lsfx/086.wav" ), 1, ATTN_NORM, 0 );
}
A_StateChange( self, st_die1 );
}
else
{
A_StateChange( self, st_remove ); // mark for removal
}
return;
}
if( deltax < PROJECTILESIZE && deltay < PROJECTILESIZE )
{ // hit the player
switch( self->type )
{
case en_needle:
damage = (US_RndT() >> 3) + 20;
break;
case en_rocket:
case en_hrocket:
case en_spark:
damage = (US_RndT()>>3) + 30;
break;
case en_fire:
damage = (US_RndT() >> 3);
break;
default:
damage = 0;
break;
}
PL_Damage( &Player, self, damage );
A_StateChange( self, st_remove ); // mark for removal
return;
}
self->tilex = self->x >> TILESHIFT;
self->tiley = self->y >> TILESHIFT;
}

View File

@@ -0,0 +1,73 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_actor_ai.h: Wolfenstein3-D entity management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_actor_ai.c.
*/
#ifndef __WOLF_ACTOR_AI_H__
#define __WOLF_ACTOR_AI_H__
#include "wolf_actors.h"
extern void A_DeathScream( entity_t *self );
extern void A_FirstSighting( entity_t *self );
extern void A_DamageActor( entity_t *self, int damage );
// hitler
extern void A_MechaSound( entity_t *self );
extern void A_Slurpie( entity_t *self );
extern void A_HitlerMorph( entity_t *self );
// angel
extern void A_Breathing( entity_t *self );
extern void A_StartAttack( entity_t *self );
extern void A_Relaunch( entity_t *self );
extern void A_Victory( entity_t *self );
// ghost
extern void A_Dormant( entity_t *self );
extern void A_StartDeathCam( entity_t *self );
// missiles
extern void T_Projectile( entity_t *self );
extern void A_Smoke( entity_t *self );
#endif /* __WOLF_ACTOR_AI_H__ */

View File

@@ -0,0 +1,471 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2001 by DarkOne the Hacker
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.
*/
/*
* wolf_actors.c: Wolfenstein3-D actor manager.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
#include "wolf_act_stat.h"
entity_t Guards[ MAX_GUARDS + 1 ], *New;
W16 NumGuards = 0;
W8 add8dir[ 9 ] = { 4, 5, 6, 7, 0, 1, 2, 3, 0 };
W8 r_add8dir[ 9 ]= { 4, 7, 6, 5, 0, 1, 2, 3, 0 };
/*
-----------------------------------------------------------------------------
Function: A_StateChange -Changes guard's state to that defined in NewState.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void A_StateChange( entity_t *ent, en_state NewState )
{
ent->state = NewState;
assert( ent->type >= 0 && ent->type < NUMENEMIES );
if ( NewState == st_remove ) {
ent->ticcount = 0;
} else {
assert( ent->state >= 0 && ent->state < NUMSTATES );
ent->ticcount = objstate[ ent->type ][ ent->state ].timeout; //0;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE int DoGuard( entity_t *ent ) // FIXME: revise!
{ // returns 0 if we must remove this Guard from Guards list, otherwise 1;
think_t think;
assert( ent->tilex >= 0 && ent->tilex < 64 );
assert( ent->tiley >= 0 && ent->tiley < 64 );
assert( ent->dir >= 0 && ent->dir <= 8 );
// ticcounts fire discrete actions separate from think functions
if ( ent->ticcount ) {
ent->ticcount -= tics;
while( ent->ticcount <= 0 )
{
assert( ent->type >= 0 && ent->type < NUMENEMIES );
assert( ent->state >= 0 && ent->state < NUMSTATES );
think = objstate[ ent->type ][ ent->state ].action; // end of state action
if( think )
{
think( ent );
if( ent->state == st_remove )
{
return 0;
}
}
ent->state = objstate[ ent->type ][ ent->state ].next_state;
if( ent->state == st_remove )
{
return 0;
}
if( ! objstate[ ent->type ][ ent->state ].timeout )
{
ent->ticcount = 0;
break;
}
ent->ticcount += objstate[ ent->type ][ ent->state ].timeout;
}
}
//
// think
//
assert( ent->type >= 0 && ent->type < NUMENEMIES );
assert( ent->state >= 0 && ent->state < NUMSTATES );
think = objstate[ ent->type ][ ent->state ].think;
if( think )
{
think( ent );
if( ent->state == st_remove )
{
return 0;
}
}
return 1;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void RemoveActor( entity_t *actor )
{
Sprite_RemoveSprite( actor->sprite );
memmove( actor, actor+1, (int)(&Guards[ NumGuards ]) - (int)(actor+1) );
NumGuards--;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void ProcessGuards( void )
{
int n, tex;
assert( NumGuards < MAX_GUARDS );
for( n = 0 ; n < NumGuards ; ++n )
{
if( ! DoGuard( &Guards[ n ] ) )
{ // remove guard from the game forever!
RemoveActor( &Guards[ n-- ] );
continue;
}
Sprite_SetPos( Guards[ n ].sprite, Guards[ n ].x, Guards[ n ].y, Guards[ n ].angle );
tex = objstate[ Guards[ n ].type ][ Guards[ n ].state ].texture;
if( objstate[ Guards[ n ].type ][ Guards[ n ].state ].rotate )
{
if( Guards[ n ].type == en_rocket || Guards[ n ].type == en_hrocket )
{
tex += r_add8dir[ Get8dir( angle_wise( FINE2RAD(Player.position.angle), FINE2RAD(Guards[ n ].angle) ) ) ];
}
else
{
tex += add8dir[ Get8dir( angle_wise( FINE2RAD(Player.position.angle), FINE2RAD(Guards[ n ].angle) ) ) ];
}
}
Sprite_SetTex( Guards[ n ].sprite, 0, tex );
}
}
/*
-----------------------------------------------------------------------------
Function: ResetGuards -Reset actors status
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void ResetGuards( void )
{
memset( Guards, 0, sizeof( Guards ) );
NumGuards = 0;
New = NULL;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC entity_t *GetNewActor( void )
{
if( NumGuards > MAX_GUARDS )
{
return NULL;
}
memset( &Guards[ NumGuards ], 0, sizeof( Guards[ 0 ] ) );
return &Guards[ NumGuards++ ];
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC entity_t *SpawnActor( enemy_t which, int x, int y, dir4type dir, LevelData_t *lvl )
{
entity_t *new_actor;
new_actor = GetNewActor();
if( ! new_actor )
{
return NULL;
}
new_actor->x = TILE2POS( x );
new_actor->y = TILE2POS( y );
new_actor->tilex = x;
new_actor->tiley = y;
assert( dir >= 0 && dir <= 4 );
new_actor->angle = dir4angle[ dir ];
new_actor->dir = dir4to8[ dir ];
new_actor->areanumber = lvl->areas[ x ][ y ];
// Com_Printf( "Actor at %i,%i had areaNum: %i\n", x, y, new_actor->areanumber );
if ( new_actor->areanumber < 0 ) {
// ambush marker tiles are listed as -3 area
new_actor->areanumber = 0;
}
assert( new_actor->areanumber >= 0 && new_actor->areanumber < NUMAREAS );
new_actor->type = which;
new_actor->health = starthitpoints[ (int)skill->value ][ which ];
new_actor->sprite = Sprite_GetNewSprite();
return new_actor;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void SpawnStand( enemy_t which, int x, int y, int dir, LevelData_t *lvl )
{
entity_t *self;
self = SpawnActor( which, x, y, dir, r_world );
if( ! self )
{
return;
}
self->state = st_stand;
self->speed = SPDPATROL;
self->ticcount = objstate[ which ][ st_stand ].timeout ? US_RndT() % objstate[ which ][ st_stand ].timeout + 1 : 0;
self->flags |= FL_SHOOTABLE;
if( lvl->tilemap[ x ][ y ] & AMBUSH_TILE )
{
self->flags |= FL_AMBUSH;
}
levelstate.total_monsters++;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void SpawnPatrol( enemy_t which, int x, int y, int dir )
{
entity_t *self;
self = SpawnActor( which, x, y, dir, r_world );
if( ! self )
{
return;
}
self->state = st_path1;
self->speed = (which == en_dog) ? SPDDOG : SPDPATROL;
self->distance = TILEGLOBAL;
self->ticcount = objstate[ which ][ st_path1 ].timeout ? US_RndT() % objstate[ which ][ st_path1 ].timeout + 1 : 0;
self->flags |= FL_SHOOTABLE;
levelstate.total_monsters++;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void SpawnDeadGuard( enemy_t which, int x, int y )
{
entity_t *self;
self = SpawnActor( which, x, y, dir4_nodir, r_world );
if( ! self )
{
return;
}
self->state = st_dead;
self->speed = 0;
self->health = 0;
self->ticcount = objstate[ which ][ st_dead ].timeout ? US_RndT() % objstate[ which ][ st_dead ].timeout + 1 : 0;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void SpawnBoss( enemy_t which, int x, int y )
{
entity_t *self;
dir4type face;
switch( which )
{
case en_boss:
case en_schabbs:
case en_fat:
case en_hitler:
face = dir4_south;
break;
case en_fake:
case en_gretel:
case en_gift:
face = dir4_north;
break;
case en_trans:
case en_uber:
case en_will:
case en_death:
case en_angel:
case en_spectre:
face = dir4_nodir;
break;
default:
face = dir4_nodir;
break;
}
self = SpawnActor( which, x, y, face, r_world );
if( ! self )
{
return;
}
self->state = which == en_spectre ? st_path1 : st_stand;
self->speed = SPDPATROL;
self->health = starthitpoints[ (int)skill->value ][ which ];
self->ticcount = objstate[ which ][ st_stand ].timeout ? US_RndT() % objstate[ which ][ st_stand ].timeout + 1 : 0;
self->flags |= FL_SHOOTABLE | FL_AMBUSH;
levelstate.total_monsters++;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void SpawnGhosts( enemy_t which, int x, int y )
{
entity_t *self;
self = SpawnActor( which, x, y, dir4_nodir, r_world );
if( ! self )
{
return;
}
self->state = st_chase1;
self->speed = SPDPATROL * 3;
self->health = starthitpoints[ (int)skill->value ][ which ];
self->ticcount = objstate[ which ][ st_chase1 ].timeout ? US_RndT() % objstate[ which ][ st_chase1 ].timeout + 1: 0;
self->flags |= FL_AMBUSH;
levelstate.total_monsters++;
}

View File

@@ -0,0 +1,172 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_actors.h: Wolfenstein3-D entity management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_actors.c
*/
#ifndef __WOLF_ACTORS_H__
#define __WOLF_ACTORS_H__
#define SPDPATROL 512
#define SPDDOG 1500
#define FL_SHOOTABLE 1
#define FL_BONUS 2
#define FL_NEVERMARK 4
#define FL_VISABLE 8
#define FL_ATTACKMODE 16
#define FL_FIRSTATTACK 32
#define FL_AMBUSH 64
#define FL_NONMARK 128
#define MAX_GUARDS 255
#define NUMENEMIES 31
#define NUMSTATES 34
#define MINACTORDIST 0x10000 // minimum dist from player center to any actor center
typedef enum
{
en_guard,
en_officer,
en_ss,
en_dog,
en_boss,
en_schabbs,
en_fake,
en_mecha,
en_hitler,
en_mutant,
en_blinky,
en_clyde,
en_pinky,
en_inky,
en_gretel,
en_gift,
en_fat,
// --- Projectiles
en_needle,
en_fire,
en_rocket,
en_smoke,
en_bj,
// --- Spear of destiny!
en_spark,
en_hrocket,
en_hsmoke,
en_spectre,
en_angel,
en_trans,
en_uber,
en_will,
en_death
} enemy_t;
typedef enum
{
st_stand,
st_path1, st_path1s, st_path2, st_path3, st_path3s, st_path4,
st_pain, st_pain1,
st_shoot1, st_shoot2, st_shoot3, st_shoot4, st_shoot5, st_shoot6, st_shoot7, st_shoot8, st_shoot9,
st_chase1, st_chase1s, st_chase2, st_chase3, st_chase3s, st_chase4,
st_die1, st_die2, st_die3, st_die4, st_die5, st_die6, st_die7, st_die8, st_die9,
st_dead,
st_remove
} en_state;
typedef struct entity_s
{
int x, y, angle;
int type;
int health;
int max_health;
int speed;
int ticcount;
int temp2;
int distance;
char tilex, tiley;
char areanumber;
int waitfordoorx, waitfordoory; // waiting on this door if non 0
W8 flags; // FL_SHOOTABLE, etc
en_state state;
dir8type dir;
int sprite;
} entity_t;
typedef void (*think_t)( entity_t *self );
typedef struct
{
char rotate; // 1-if object can be rotated, 0 if one sprite for every direction
int texture; // base object's state texture if rotation is on facing player
int timeout; // after how man ticks change state to .next_state
think_t think; // what to do every frame
think_t action; // what to do once per state
en_state next_state; // next state
} stateinfo;
extern entity_t Guards[ MAX_GUARDS + 1 ];
extern entity_t *New;
extern W16 NumGuards;
extern stateinfo objstate[ NUMENEMIES ][ NUMSTATES ];
extern void ResetGuards(void);
extern entity_t *GetNewActor( void );
extern entity_t *SpawnActor( enemy_t which, int x, int y, dir4type dir, LevelData_t *lvl );
extern void A_StateChange( entity_t *Guard, en_state NewState );
extern void SpawnStand( enemy_t which, int tilex, int tiley, int dir, LevelData_t *lvl );
extern void SpawnPatrol( enemy_t which, int tilex, int tiley, int dir );
extern void SpawnDeadGuard( enemy_t which, int x, int y );
extern void SpawnBoss( enemy_t which, int x, int y );
extern void SpawnGhosts( enemy_t which, int x, int y );
#endif /* __WOLF_ACTORS_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_ai_com.h: Wolfenstein3-D entity management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_ai_com.c
*/
#ifndef __WOLF_AI_COM_H__
#define __WOLF_AI_COM_H__
#include "wolf_actors.h"
// common AI functions
extern void T_Stand( entity_t *self );
extern void T_Path( entity_t *self );
extern void T_Ghosts( entity_t *self );
extern void T_Chase( entity_t *self );
extern void T_Bite( entity_t *self );
extern void T_DogChase( entity_t *self );
extern void T_BossChase( entity_t *self );
extern void T_Fake( entity_t *self );
extern void T_Shoot( entity_t *self );
extern void T_UShoot( entity_t *self );
extern void T_Launch( entity_t *self );
#endif /* __WOLF_AI_COM_H__ */

View File

@@ -0,0 +1,170 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_areas.c: Wolfenstein3-D area management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Acknowledgement:
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
Open doors connect two areas, so sounds will travel between them and sight
will be checked when the player is in a connected area.
Areaconnect is incremented/decremented by each door. If >0 they connect.
Every time a door opens or closes the areabyplayer matrix gets recalculated.
An area is true if it connects with the player's current spor.
*/
#include "../wolfiphone.h"
W8 areaconnect[ NUMAREAS ][ NUMAREAS ];
_boolean areabyplayer[ NUMAREAS ];
/*
-----------------------------------------------------------------------------
Function: Areas_RecursiveConnect() -Scans outward from playerarea,
marking all connected areas.
Parameters: areanumber -[in] area.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Areas_RecursiveConnect( int areanumber )
{
int i;
for( i = 0 ; i < NUMAREAS ; ++i )
{
if( areaconnect[ areanumber ][ i ] && ! areabyplayer[ i ] )
{
areabyplayer[ i ] = true;
Areas_RecursiveConnect( i );
}
}
}
/*
-----------------------------------------------------------------------------
Function: Areas_ConnectAreas() -Connect area.
Parameters: areanumber -[in] area.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Areas_ConnectAreas( int areanumber )
{
int c = 0;
int i;
assert( areanumber < NUMAREAS );
memset( areabyplayer, 0, sizeof( areabyplayer ) );
areabyplayer[ areanumber ] = true;
Areas_RecursiveConnect( areanumber );
for ( i = 0 ; i < NUMAREAS ; i++ ) {
if ( areabyplayer[i] ) {
c++;
}
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Areas_InitAreas( int areanumber )
{
memset( areaconnect, 0, sizeof( areaconnect ) );
memset( areabyplayer, 0, sizeof( areabyplayer ) );
areabyplayer[ areanumber ] = true;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Areas_JoinAreas( int area1, int area2 )
{// FIXME: check for overflow!
areaconnect[ area1 ][ area2 ]++;
areaconnect[ area2 ][ area1 ]++;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Areas_DisconnectAreas( int area1, int area2 )
{// FIXME: check for underflow!
areaconnect[ area1 ][ area2 ]--;
areaconnect[ area2 ][ area1 ]--;
}

136
wolf3d/code/wolf/wolf_bj.c Normal file
View File

@@ -0,0 +1,136 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
#include "../wolfiphone.h"
#define BJRUNSPEED 2048
#define BJJUMPSPEED 680
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
void SpawnBJVictory( void )
{
entity_t *bj;
bj = SpawnActor( en_bj, POS2TILE(Player.position.origin[0]), POS2TILE(Player.position.origin[1]), dir4_north, r_world );
if( ! bj )
{
return;
}
bj->x = Player.position.origin[ 0 ];
bj->y = Player.position.origin[ 1 ];
bj->state = st_path1;
bj->speed = BJRUNSPEED;
bj->flags = FL_NONMARK; // FL_NEVERMARK;
bj->temp2 = 6;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
void T_BJRun( entity_t *Guard )
{
// MoveObj(Guard, Guard->speed);
if( ! Guard->distance )
{
Guard->distance = TILEGLOBAL;
if ( !(--Guard->temp2) )
{
A_StateChange( Guard, st_shoot1 );
Guard->speed = BJJUMPSPEED;
return;
}
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
void T_BJJump( entity_t *Guard )
{
// MoveObj(Guard, Guard->speed);
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
void T_BJYell( entity_t *Guard )
{
Sound_StartSound( NULL, 0, CHAN_VOICE, Sound_RegisterSound( "sfx/082.wav" ), 1, ATTN_NORM, 0 );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
void T_BJDone( entity_t *Guard )
{
Player.playstate = ex_victory; // exit castle tile
}

View File

@@ -0,0 +1,59 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_bj.h: Wolfenstein3-D bj code .
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_bj.c
*/
#ifndef __WOLF_BJ_H__
#define __WOLF_BJ_H__
extern void SpawnBJVictory( void );
extern void T_BJRun( entity_t *Guard );
extern void T_BJJump( entity_t *Guard );
extern void T_BJYell( entity_t *Guard );
extern void T_BJDone( entity_t *Guard );
#endif /* __WOLF_BJ_H__ */

View File

@@ -0,0 +1,91 @@
/*
Copyright (C) 2004 Michael Liebscher
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.
*/
#include "../wolfiphone.h"
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Client_PrepRefresh( const char *r_mapname )
{
char mapname[ 32 ];
if( ! r_mapname || ! *r_mapname )
{
return;
}
if( g_version->value == SPEAROFDESTINY )
{
spritelocation = SODSPRITESDIRNAME;
}
else
{
spritelocation = WL6SPRITESDIRNAME;
}
my_strlcpy( mapname, r_mapname, sizeof( mapname ) ); // skip "maps/"
// !@# fix crash bug if you type something short...
if ( strlen( mapname ) > 4 && !strcmp( mapname + strlen( mapname ) - 4, ".map" ) ) {
mapname[ strlen( mapname ) - 4 ] = '\0'; // cut off ".map"
}
// register models, pics, and skins
R_BeginRegistration( mapname );
if( r_world == NULL )
{
return;
}
Com_Printf( "Map: %s\n", r_world->mapName );
Level_ScanInfoPlane( r_world ); // Spawn items/guards
Com_Printf( "Spawning Entities\n" );
PL_Spawn( r_world->pSpawn, r_world ); // Spawn Player
Com_Printf( "Caching Textures and Sounds\n" );
Level_PrecacheTextures_Sound( r_world );
// clear any lines of console text
Con_ClearNotify();
Sound_StartBGTrack( levelData.musicName, levelData.musicName );
Player.playstate = ex_playing;
}
int tics;

View File

@@ -0,0 +1,506 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_doors.c: Wolfenstein 3-D door management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Acknowledgement:
* Portion of this code was derived from Wolfenstein 3-D, and was originally
* written by Id Software, Inc.
*
*/
#include "../wolfiphone.h"
#define CLOSEWALL MINDIST // Space between wall & player
#define MAXDOORS 64 // max number of sliding doors
/*
-----------------------------------------------------------------------------
Function: Door_ResetDoors -Resets doors status
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Door_ResetDoors( LevelDoors_t *lvldoors )
{
lvldoors->doornum = 0;
memset( lvldoors->Doors, 0, sizeof( lvldoors->Doors ) );
memset( lvldoors->DoorMap, 0, sizeof( lvldoors->DoorMap ) );
}
/*
-----------------------------------------------------------------------------
Function: Door_SpawnDoor -Spawns door at x, y, position.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int Door_SpawnDoor( LevelDoors_t *lvldoors, int x, int y, int type )
{
if( lvldoors->doornum >= MAXDOORS )
{
Com_DPrintf( "[%s]: Too many Doors on level! (%d)\n", "wolf_doors.c", lvldoors->doornum );
return 0;
}
switch( type )
{
case 0x5A:
lvldoors->DoorMap[ x ][ y ].type = DOOR_VERT;
lvldoors->DoorMap[ x ][ y ].vertical= true;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DDOOR + 1;
break;
case 0x5B:
lvldoors->DoorMap[ x ][ y ].type = DOOR_HORIZ;
lvldoors->DoorMap[ x ][ y ].vertical = false;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DDOOR;
break;
case 0x5C:
lvldoors->DoorMap[ x ][ y ].type = DOOR_G_VERT;
lvldoors->DoorMap[ x ][ y ].vertical = true;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DLOCK;
break;
case 0x5D:
lvldoors->DoorMap[ x ][ y ].type = DOOR_G_HORIZ;
lvldoors->DoorMap[ x ][ y ].vertical = false;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DLOCK;
break;
case 0x5E:
lvldoors->DoorMap[ x ][ y ].type = DOOR_S_VERT;
lvldoors->DoorMap[ x ][ y ].vertical = true;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DLOCK + 1;
break;
case 0x5F:
lvldoors->DoorMap[ x ][ y ].type = DOOR_S_HORIZ;
lvldoors->DoorMap[ x ][ y ].vertical = false;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DLOCK + 1;
break;
case 0x64:
lvldoors->DoorMap[ x ][ y ].type = DOOR_E_VERT;
lvldoors->DoorMap[ x ][ y ].vertical = true;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DELEV + 1;
break;
case 0x65:
lvldoors->DoorMap[ x ][ y ].type = DOOR_E_HORIZ;
lvldoors->DoorMap[ x ][ y ].vertical = false;
lvldoors->DoorMap[ x ][ y ].texture = TEX_DELEV;
break;
default:
Com_DPrintf( "Door_SpawnDoor: Unknown door type: %d\n", type );
return 0;
}
lvldoors->DoorMap[ x ][ y ].tilex = x;
lvldoors->DoorMap[ x ][ y ].tiley = y;
lvldoors->DoorMap[ x ][ y ].action = dr_closed;
lvldoors->Doors[ lvldoors->doornum ] = &lvldoors->DoorMap[ x ][ y ];
lvldoors->doornum++;
return lvldoors->doornum - 1;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Door_SetAreas( LevelDoors_t *lvldoors, int (*areas)[64] )
{
int n, x, y;
for( n = 0 ; n < lvldoors->doornum ; ++n )
{
x = lvldoors->Doors[ n ]->tilex;
y = lvldoors->Doors[ n ]->tiley;
if( lvldoors->Doors[ n ]->vertical )
{
lvldoors->Doors[ n ]->area1 = areas[ x + 1 ][ y ] >= 0 ? areas[ x + 1 ][ y ] : 0;
lvldoors->Doors[ n ]->area2 = areas[ x - 1 ][ y ] >= 0 ? areas[ x - 1 ][ y ] : 0;
}
else
{
lvldoors->Doors[ n ]->area1 = areas[ x ][ y + 1 ] >= 0 ? areas[ x ][ y + 1 ] : 0;
lvldoors->Doors[ n ]->area2 = areas[ x ][ y - 1 ] >= 0 ? areas[ x ][ y - 1 ] : 0;
}
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE W8 CanCloseDoor( int x, int y, char vert )
{
int n;
if( POS2TILE( Player.position.origin[ 0 ] ) == x &&
POS2TILE( Player.position.origin[ 1 ] ) == y )
{
return 0;
}
if( vert )
{
if( POS2TILE( Player.position.origin[ 1 ] ) == y )
{
if( POS2TILE( Player.position.origin[ 0 ] + CLOSEWALL ) == x )
{
return 0;
}
if( POS2TILE( Player.position.origin[ 0 ] - CLOSEWALL ) == x )
{
return 0;
}
}
for( n = 0 ; n < NumGuards ; ++n )
{
if( Guards[ n ].tilex == x && Guards[ n ].tiley == y )
{
return 0; // guard in door
}
if( Guards[ n ].tilex == x - 1 &&
Guards[ n ].tiley == y &&
POS2TILE( Guards[ n ].x + CLOSEWALL ) == x )
{
return 0; // guard in door
}
if( Guards[ n ].tilex == x + 1 &&
Guards[ n ].tiley == y &&
POS2TILE( Guards[ n ].x - CLOSEWALL ) == x )
{
return 0; // guard in door
}
}
}
else
{
if( POS2TILE( Player.position.origin[ 0 ] ) == x )
{
if( POS2TILE( Player.position.origin[ 1 ] + CLOSEWALL ) == y )
{
return 0;
}
if( POS2TILE( Player.position.origin[ 1 ] - CLOSEWALL ) == y )
{
return 0;
}
}
for( n = 0 ; n < NumGuards ; ++n )
{
if( Guards[ n ].tilex == x && Guards[ n ].tiley == y )
{
return 0; // guard in door
}
if( Guards[ n ].tilex == x &&
Guards[ n ].tiley == y - 1 &&
POS2TILE( Guards[ n ].y + CLOSEWALL ) == y )
{
return 0; // guard in door
}
if( Guards[ n ].tilex == x &&
Guards[ n ].tiley == y + 1 &&
POS2TILE( Guards[ n ].y - CLOSEWALL ) == y )
{
return 0; // guard in door
}
}
}
return 1;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Door_OpenDoor( doors_t *Door )
{
if( Door->action == dr_open )
{
Door->ticcount = 0; // reset opened time
}
else
{
Door->action = dr_opening; // start opening it
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Door_ChangeDoorState( doors_t *Door )
{
if( Door->action < dr_opening )
{
Door_OpenDoor( Door );
}
else if( Door->action == dr_open && CanCloseDoor( Door->tilex, Door->tiley, Door->vertical ) )
{
// !@# for the iphone with automatic using, don't allow any door close actions
// Door->action = dr_closing;
// Door->ticcount = DOOR_FULLOPEN;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Door_ProcessDoors_e( LevelDoors_t *lvldoors, int t_tk )
{
int n;
for( n = 0 ; n < lvldoors->doornum ; ++n )
{
switch( lvldoors->Doors[ n ]->action )
{
case dr_closed: // this door is closed!
continue;
case dr_opening:
if( lvldoors->Doors[ n ]->ticcount >= DOOR_FULLOPEN ) // door fully opened!
{
lvldoors->Doors[ n ]->action = dr_open;
lvldoors->Doors[ n ]->ticcount = 0;
}
else // opening!
{
if( lvldoors->Doors[ n ]->ticcount == 0 )
{ // door is just starting to open, so connect the areas
Areas_JoinAreas( lvldoors->Doors[ n ]->area1, lvldoors->Doors[ n ]->area2 );
Areas_ConnectAreas( Player.areanumber );
if( areabyplayer[ lvldoors->Doors[ n ]->area1 ] ) // Door Opening sound!
{
Sound_StartSound( NULL, 1, CHAN_AUTO, Sound_RegisterSound( "sfx/010.wav" ), 1, ATTN_STATIC, 0 );
}
}
lvldoors->Doors[n]->ticcount += t_tk;
if( lvldoors->Doors[ n ]->ticcount > DOOR_FULLOPEN )
{
lvldoors->Doors[ n ]->ticcount = DOOR_FULLOPEN;
}
}
break;
case dr_closing:
if( lvldoors->Doors[ n ]->ticcount <= 0 ) // door fully closed! disconnect areas!
{
Areas_DisconnectAreas( lvldoors->Doors[ n ]->area1, lvldoors->Doors[ n ]->area2 );
Areas_ConnectAreas( Player.areanumber );
lvldoors->Doors[ n ]->ticcount = 0;
lvldoors->Doors[ n ]->action = dr_closed;
}
else // closing!
{
if( lvldoors->Doors[ n ]->ticcount == DOOR_FULLOPEN )
{
if( areabyplayer[ lvldoors->Doors[ n ]->area1 ] ) // Door Closing sound!
{
Sound_StartSound( NULL, 1, CHAN_AUTO, Sound_RegisterSound( "sfx/007.wav" ), 1, ATTN_STATIC, 0 );
}
}
lvldoors->Doors[ n ]->ticcount -= t_tk;
if( lvldoors->Doors[ n ]->ticcount < 0 )
{
lvldoors->Doors[ n ]->ticcount = 0;
}
}
break;
case dr_open:
if( lvldoors->Doors[ n ]->ticcount > DOOR_MINOPEN )
{ // If player or something is in door do not close it!
if( ! CanCloseDoor( lvldoors->Doors[ n ]->tilex, lvldoors->Doors[ n ]->tiley, lvldoors->Doors[ n ]->vertical ) )
{
lvldoors->Doors[ n ]->ticcount = DOOR_MINOPEN; // do not close door immediately!
}
}
if( lvldoors->Doors[ n ]->ticcount >= DOOR_TIMEOUT )
{ // Door timeout, time to close it!
lvldoors->Doors[ n ]->action = dr_closing;
lvldoors->Doors[ n ]->ticcount = DOOR_FULLOPEN;
}
else
{ // Increase timeout!
lvldoors->Doors[ n ]->ticcount += t_tk;
}
break;
} // End switch lvldoors->Doors[ n ].action
} // End for n = 0 ; n < lvldoors->doornum ; ++n
}
/*
-----------------------------------------------------------------------------
Function: Door_Opened -Check to see if a door is open.
Parameters:
Returns: DOOR_FULLOPEN Door is opened
0 Door is closed
>0 <DOOR_FULLOPEN Door is partially opened.
Notes:
If there are no doors in tile assume a closed door!
-----------------------------------------------------------------------------
*/
PUBLIC int Door_Opened( LevelDoors_t *lvldoors, int x, int y )
{
return lvldoors->DoorMap[ x ][ y ].action == dr_open ? DOOR_FULLOPEN : lvldoors->DoorMap[ x ][ y ].ticcount;
}
/*
-----------------------------------------------------------------------------
Function: Door_TryUse -Try to use a door with keys that the player has.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC _boolean Door_TryUse( doors_t *Door, int keys )
{
switch( Door->type )
{
case DOOR_VERT:
case DOOR_HORIZ:
case DOOR_E_VERT:
case DOOR_E_HORIZ:
Door_ChangeDoorState( Door ); // does not require key!
break;
case DOOR_G_VERT:
case DOOR_G_HORIZ:
if( keys & ITEM_KEY_1 )
{
Door_ChangeDoorState( Door );
}
else
{
iphoneSetNotifyText( "You need a gold key" );
}
break;
case DOOR_S_VERT:
case DOOR_S_HORIZ:
if( keys & ITEM_KEY_2 )
{
Door_ChangeDoorState( Door );
}
else
{
iphoneSetNotifyText( "You need a silver key" );
}
break;
}
return true; // FIXME
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,292 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_level.h: Wolfenstein3-D level management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Acknowledgement:
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_areas.c, wolf_doors.c, wolf_level.c and
wolf_pushwalls.c
*/
#ifndef __WOLF_LEVEL_H__
#define __WOLF_LEVEL_H__
///////////////////
//
// Areas
//
///////////////////
#define NUMAREAS 37 // number of areas
#define FIRSTAREA 0x6B // first area in map data (it is by the way a way to the secret floor!)
#define AMBUSHTILE 0x6A // def guard
#define AMBUSH -2
///////////////////
//
// Doors
//
///////////////////
#define MAX_DOORS 256
#define DOOR_TIMEOUT 300
#define DOOR_MINOPEN 50
#define DOOR_FULLOPEN 63
#define DOOR_VERT 255
#define DOOR_HORIZ 254
#define DOOR_E_VERT 253
#define DOOR_E_HORIZ 252
#define DOOR_G_VERT 251
#define DOOR_G_HORIZ 250
#define DOOR_S_VERT 249
#define DOOR_S_HORIZ 248
#define FIRST_DOOR 248
#define LAST_LOCK 251
#define TEX_DOOR 126
// texture IDs used by cache routines
#define TEX_DDOOR (0 + TEX_DOOR) // Simple Door
#define TEX_PLATE (2 + TEX_DOOR) // Door Plate
#define TEX_DELEV (4 + TEX_DOOR) // Elevator Door
#define TEX_DLOCK (6 + TEX_DOOR) // Locked Door
///////////////////
//
// Level
//
///////////////////
#define WALL_TILE 1
#define PUSHWALL_TILE (1 << 20)
#define DOOR_TILE 2
#define SECRET_TILE 4
#define DRESS_TILE 8
#define BLOCK_TILE 16
#define ACTOR_TILE 32
#define DEADACTOR_TILE 64
#define POWERUP_TILE 128
#define AMBUSH_TILE 256
#define EXIT_TILE 512
#define SECRETLEVEL_TILE 1024
#define ELEVATOR_TILE (1 << 11)
#define TILE_IS_E_TURN (1 << 12)
#define TILE_IS_NE_TURN (1 << 13)
#define TILE_IS_N_TURN (1 << 14)
#define TILE_IS_NW_TURN (1 << 15)
#define TILE_IS_W_TURN (1 << 16)
#define TILE_IS_SW_TURN (1 << 17)
#define TILE_IS_S_TURN (1 << 18)
#define TILE_IS_SE_TURN (1 << 19)
#define SOLID_TILE (WALL_TILE | BLOCK_TILE | PUSHWALL_TILE)
#define BLOCKS_MOVE_TILE (WALL_TILE | BLOCK_TILE | PUSHWALL_TILE | ACTOR_TILE)
#define WAYPOINT_TILE (TILE_IS_E_TURN | TILE_IS_NE_TURN | TILE_IS_N_TURN | TILE_IS_NW_TURN | TILE_IS_W_TURN | TILE_IS_SW_TURN | TILE_IS_S_TURN | TILE_IS_SE_TURN )
///////////////////
//
// Doors
//
///////////////////
typedef enum
{
dr_closing = -1,
dr_closed,
dr_opening,
dr_open
} dr_state;
typedef struct
{
int tilex, tiley;
_boolean vertical;
int ticcount;
dr_state action;
int area1, area2;
/*DOOR_VERT 255
DOOR_HORIZ 254
DOOR_E_VERT 253
DOOR_E_HORIZ 252
DOOR_G_VERT 251
DOOR_G_HORIZ 250
DOOR_S_VERT 249
DOOR_S_HORIZ 248*/
int type;
int texture;
} doors_t;
typedef struct
{
int doornum;
doors_t *Doors[ 256 ];
doors_t DoorMap[ 64 ][ 64 ];
} LevelDoors_t;
#define MAX_POWERUPS 1000
///////////////////
//
// Level
//
///////////////////
typedef struct
{
char fname[ 32 ]; /* Map filename */
W16 Plane1[ 64 * 64 ]; /* walls */
W16 Plane2[ 64 * 64 ]; /* objects */
W16 Plane3[ 64 * 64 ]; /* other */
long tilemap[ 64 ][ 64 ]; // wall values only
W8 spotvis[ 64 ][ 64 ];
// objtype *actorat[ 64 ][ 64 ];
// this is an array of references to texture descriptions
// the renderer must know what to draw by this number
int wall_tex_x[ 64 ][ 64 ]; // x_wall
int wall_tex_y[ 64 ][ 64 ]; // y_wall
// this is a (0-based) array of area numbers!
// must be all filled by level loading sub
// if -1 it is a wall, if -2 it is a door, if -3 it is unknown
int areas[ 64 ][ 64 ];
LevelDoors_t Doors;
placeonplane_t pSpawn; // player spawn place
powerup_t powerups[MAX_POWERUPS];
int numPowerups;
sprite_t sprites[ MAX_SPRITES ];
int numSprites;
char mapName[128]; /* Map name */
char musicName[128]; /* Music file name */
colour3_t ceilingColour, floorColour;
W8 tileEverVisible[ 64 ][ 64 ]; // for automap
} LevelData_t;
typedef struct statinfo_t
{
_boolean block;
int powerup;
} statinfo_t;
extern LevelData_t *r_world;
extern LevelData_t levelData;
extern LevelData_t *Level_LoadMap( const char *levelname );
extern void Level_PrecacheTextures_Sound( LevelData_t *lvl );
extern _boolean Level_CheckLine( SW32 x1, SW32 y1, SW32 x2, SW32 y2, LevelData_t *lvl );
extern void Level_ScanInfoPlane( LevelData_t *lvl );
///////////////////
//
// Doors
//
///////////////////
extern void Door_ResetDoors( LevelDoors_t *lvl );
extern int Door_SpawnDoor( LevelDoors_t *lvl, int x, int y, int type );
extern void Door_SetAreas( LevelDoors_t *lvl, int (*areas)[64] );
extern void Door_OpenDoor( doors_t *Door );
extern void Door_ProcessDoors_e( LevelDoors_t *lvl, int t_tk );
extern int Door_Opened( LevelDoors_t *lvl, int x, int y );
extern _boolean Door_TryUse( doors_t *Door, int keys );
///////////////////
//
// Areas
//
///////////////////
extern _boolean areabyplayer[ NUMAREAS ];
extern void Areas_ConnectAreas( int areanumber );
extern void Areas_InitAreas( int areanumber );
extern void Areas_JoinAreas( int area1, int area2 );
extern void Areas_DisconnectAreas( int area1, int area2 );
///////////////////
//
// Push Walls
//
///////////////////
typedef struct
{
_boolean active;
int PWtilesmoved;
int PWpointsmoved;
dir4type dir;
int x, y;
int dx, dy;
int tex_x, tex_y;
} Pwall_t;
extern Pwall_t PWall;
extern void PushWall_Reset( void );
extern _boolean PushWall_Push( int x, int y, dir4type dir );
extern void PushWall_Process( void );
#endif /* __WOLF_LEVEL_H__ */

View File

@@ -0,0 +1,150 @@
/*
Copyright (C) 2004 Michael Liebscher
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.
*/
/*
* wolf_local.h: Wolfenstein3-D init.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_main.c
*/
#ifndef __WOLF_LOCAL_H__
#define __WOLF_LOCAL_H__
// Game Version
#define WOLFENSTEINWL6 0x00
#define SPEAROFDESTINY 0x01
#define TILEGLOBAL 0x10000
#define HALFTILE 0x8000
#define TILESHIFT 16
#define MINDIST (0x5800)
typedef enum difficulty_e
{
gd_baby,
gd_easy,
gd_medium,
gd_hard
} difficulty_t;
//
// this structure is cleared as each map is entered
//
typedef struct
{
int framenum;
float time;
char level_name[ MAX_OSPATH ]; // the descriptive name (Outer Base, etc)
char mapname[ MAX_OSPATH ]; // the server name (base1, etc)
char nextmap[ MAX_OSPATH ]; // go here when fraglimit is hit
// intermission state
W32 levelCompleted; // in case the game was saved at the intermission
W32 floornum;
float fpartime;
char spartime[6];
W32 total_secrets;
W32 found_secrets;
W32 total_treasure;
W32 found_treasure;
W32 total_monsters;
W32 killed_monsters;
} level_locals_t;
extern level_locals_t levelstate;
typedef struct
{
W32 total_secrets;
W32 found_secrets;
W32 total_treasure;
W32 found_treasure;
W32 total_monsters;
W32 killed_monsters;
W32 time;
} LRstruct;
extern LRstruct LevelRatios;
extern cvar_t *g_version;
extern cvar_t *episode;
extern cvar_t *skill;
extern int tics;
W32 floornumber;
extern void Game_Init( void );
extern void Game_Reset( void );
extern void ProcessGuards( void );
#define WL6SPRITESDIRNAME "sprites"
#define SODSPRITESDIRNAME "sodsprites"
extern char *spritelocation;
#endif /* __WOLF_LOCAL_H__ */

View File

@@ -0,0 +1,87 @@
/*
Copyright (C) 2004-2005 Michael Liebscher
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.
*/
#include "../wolfiphone.h"
level_locals_t levelstate;
LRstruct LevelRatios;
cvar_t *g_version; // Wolfenstein or Spear of Destiny
cvar_t *episode;
cvar_t *skill;
char *spritelocation = WL6SPRITESDIRNAME;
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Game_Reset( void )
{
memset( &levelstate, 0, sizeof( levelstate ) );
}
extern void Map_f( void );
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Game_Init( void )
{
Com_Printf( "\n------ Game Init ------\n" );
episode = Cvar_Get( "episode", "0", CVAR_ARCHIVE );
skill = Cvar_Get( "skill", "1", CVAR_ARCHIVE );
g_version = Cvar_Get( "g_version", "0", CVAR_ARCHIVE );
#ifndef LITE
Cmd_AddCommand( "map", Map_f );
#endif
G_Build_Tables();
Powerup_Reset();
Sprite_Reset();
Game_Reset();
PL_Init();
Com_Printf( "\n-----------------------\n" );
}

View File

@@ -0,0 +1,341 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000 by DarkOne the Hacker
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.
*/
/*
* wolf_math.c: Wolfenstein 3-D math routines.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*
*/
#include "../wolfiphone.h"
#define XRES 640
#define YRES 480
// ------------------------- * LUTs * -------------------------
double SinTable[ ANG_360 + ANG_90 + 1 ],
*CosTable = SinTable + ANG_90,
TanTable[ ANG_360 + 1 ];
int XnextTable[ ANG_360 + 1 ],
YnextTable[ ANG_360 + 1 ];
int ColumnAngle[ 640 ]; // ViewAngle=PlayerAngle+ColumnAngle[curcolumn]; /in fines/
char dx4dir[5]={1, 0, -1, 0, 0}; // dx & dy based on direction
char dy4dir[5]={0, 1, 0, -1, 0};
char dx8dir[9]={1, 1, 0, -1, -1, -1, 0, 1, 0}; // dx & dy based on direction
char dy8dir[9]={0, 1, 1, 1, 0, -1, -1, -1, 0};
dir4type opposite4[5]={2, 3, 0, 1, 4};
dir8type opposite8[9]={4, 5, 6, 7, 0, 1, 2, 3, 8};
dir8type dir4to8[5]={0, 2, 4, 6, 8};
dir8type diagonal[9][9]=
{
/* east */ {dir8_nodir, dir8_nodir, dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southeast, dir8_nodir, dir8_nodir},
{dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
/* north */ {dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
{dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
/* west */ {dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir},
{dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
/* south */ {dir8_southeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
{dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir},
{dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir}
};
// dir of delta tooks dx{-1|0|1}+1 & dy{-1|0|1}+1 and give direction
dir4type dir4d[3][3]={{dir4_nodir, dir4_west , dir4_nodir},
{dir4_south, dir4_nodir, dir4_north},
{dir4_nodir, dir4_east , dir4_nodir}};
int dir8angle[9]={ANG_0, ANG_45, ANG_90, ANG_135, ANG_180, ANG_225, ANG_270, ANG_315, ANG_0};
int dir4angle[5]={ANG_0, ANG_90, ANG_180, ANG_270, ANG_0};
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int G_Build_Tables( void )
{
double angle, tanfov2, tanval, value;
int n;
for( n = 0 ; n <= ANG_90 ; ++n )
{
angle = FINE2RAD( n );
value = sin( angle );
SinTable[ n ] = SinTable[ ANG_180 - n ] = SinTable[ n + ANG_360 ] = value;
SinTable[ ANG_180 + n ] = SinTable[ ANG_360 - n ] = -value;
}
for( n = 0 ; n <= ANG_360 ; ++n )
{
angle = FINE2RAD( n ); //angle is in radians, n is in FINEs
if( n == ANG_90 || n == ANG_270 )
{
TanTable[ n ] = tan( FINE2RAD( n - 0.5 ) ); // infinity
YnextTable[ n ] = (int)(FLOATTILE * tan( FINE2RAD( n - 0.5 ) )); // infinity
}
else
{
TanTable[ n ] = tan( angle );
YnextTable[ n ] = (int)(FLOATTILE * tan( angle ));
}
if( n == ANG_0 || n == ANG_360 )
XnextTable[ n ] = (int)(FLOATTILE / tan( FINE2RAD( n + 0.5 ) )); // infinity
else if( n == ANG_180 )
XnextTable[ n ] = (int)(FLOATTILE / tan(FINE2RAD( n - 0.5 ) )); // -infinity
else if( n == ANG_90 || n == ANG_270 )
XnextTable[ n ] = 0;
else
XnextTable[ n ] = (int)(FLOATTILE / tan( angle ));
}
tanfov2 = TanDgr( CalcFov( 75, XRES, YRES) / 2.0 ) * ((float)XRES / (float)YRES );
for( n = 0 ; n < XRES ; ++n )
{
tanval = tanfov2 * (-1.0 + 2.0 * (double)n / (double)(XRES-1) );
ColumnAngle[ n ] = (int)RAD2FINE( atan( tanval ) );
}
US_InitRndT( 1 ); // random number generators
return 1;
}
/*
-----------------------------------------------------------------------------
Function: NormalizeAngle -clips angle to [0..360] bounds.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int NormalizeAngle( int alpha )
{
if( alpha > ANG_360 )
alpha %= ANG_360;
if(alpha<ANG_0)
alpha = ANG_360 - (-alpha) % ANG_360;
return alpha;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC quadrant GetQuadrant( float angle )
{
angle = normalize_angle( angle );
if( angle < M_PI / 2 )
{
return q_first;
}
else if( angle < M_PI )
{
return q_second;
}
else if( angle < 3 * M_PI / 2 )
{
return q_third;
}
else
{
return q_fourth;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC dir4type Get4dir( float angle )
{
angle = normalize_angle( angle + M_PI / 4 );
if( angle < M_PI / 2 )
{
return dir4_east;
}
else if( angle < M_PI )
{
return dir4_north;
}
else if( angle < 3 * M_PI / 2 )
{
return dir4_west;
}
else
{
return dir4_south;
}
}
/*
-----------------------------------------------------------------------------
Function: Get8dir -Get 8 point direction.
Parameters: angle -[in] Radian angle.
Returns: Directional point.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC dir8type Get8dir( float angle )
{
angle = normalize_angle( angle + M_PI / 12 );
if( angle <= (M_PI / 4) )
{
return dir8_east;
}
else if( angle < (M_PI / 2) )
{
return dir8_northeast;
}
else if( angle <= (3 * M_PI / 4) )
{
return dir8_north;
}
else if( angle < M_PI )
{
return dir8_northwest;
}
else if( angle <= (5 * M_PI / 4) )
{
return dir8_west;
}
else if( angle < (3 * M_PI / 2) )
{
return dir8_southwest;
}
else if( angle <= (7 * M_PI / 4) )
{
return dir8_south;
}
else
{
return dir8_southeast;
}
}
/*
-----------------------------------------------------------------------------
Function: Point2LineDist -calculates distance between a point (x, y) and
a line.
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int Point2LineDist( int x, int y, int a )
{
return ABS( (int)(x * SinTable[ a ] - y * CosTable[ a ]) );
}
/*
-----------------------------------------------------------------------------
Function: LineLen2Point -Calculates line length to the point nearest to (poin)
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int LineLen2Point( int x, int y, int a )
{
return (int)(x * CosTable[ a ] + y * SinTable[ a ] );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
Function returns angle in radians
point2 = {x,y}
/ |
/ |
/ |
/a______|----------> x
point1 = {x, y}
-----------------------------------------------------------------------------
*/
PUBLIC float TransformPoint( double Point1X, double Point1Y, double Point2X, double Point2Y )
{
float angle;
angle = atan2( Point1Y - Point2Y, Point1X - Point2X );
return normalize_angle( angle );
}

View File

@@ -0,0 +1,147 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000 by DarkOne the Hacker
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.
*/
/*
* wolf_math.h: Wolfenstein 3-D math routines.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*
*/
/*
Notes:
This module is implemented by wolf_math.c
*/
#ifndef __WOLF_MATH_H__
#define __WOLF_MATH_H__
#define FLOATTILE 65536.0f
// Angle Direction Types & LUTs (Hard Coded! Please do not mess them)
typedef enum {q_first, q_second, q_third, q_fourth} quadrant;
typedef enum {dir4_east, dir4_north, dir4_west, dir4_south, dir4_nodir} dir4type;
typedef enum { dir8_east, dir8_northeast, dir8_north, dir8_northwest, dir8_west,
dir8_southwest, dir8_south, dir8_southeast, dir8_nodir} dir8type;
extern char dx4dir[5], dy4dir[5], dx8dir[9], dy8dir[9];
extern dir4type opposite4[5], dir4d[3][3];
extern dir8type opposite8[9], dir4to8[5], diagonal[9][9];
extern int dir8angle[9], dir4angle[5];
// ------------------------- * Vectors * -------------------------
// Vectors & angles for 3D-Space
typedef struct
{
long origin[2];
long angle;
} placeonplane_t;
// ------------------------- * Some Macroses * -------------------------
#define max_of_2(a, b) ((a)>(b)?(a):(b))
#define LABS(x) ((long)(x)>0?(x):-(x))
#define TILE2POS(a) (((a)<<TILESHIFT)+HALFTILE)
#define POS2TILE(a) ((a)>>TILESHIFT)
#define POS2TILEf(a) ((a)/FLOATTILE)
// ------------------------- * vvv FINE angles vvv * -------------------------
#define ASTEP 0.0078125f // 1 FINE=x DEGREES
#define ASTEPRAD 0.000136354f // 1 FINE=x RADIANS
#define ANG_1RAD 7333.8598 // 1 RADIAN=x FINES
#define ANG_0 0 //(int)((float)0/ASTEP)
#define ANG_1 128 //(int)((float)1/ASTEP)
#define ANG_6 768 //(int)((float)6/ASTEP)
#define ANG_15 1920 //(int)((float)15/ASTEP)
#define ANG_22_5 2880 //(int)((float)22.5/ASTEP)
#define ANG_30 3840 //(int)((float)30/ASTEP)
#define ANG_45 5760 //(int)((float)45/ASTEP)
#define ANG_67_5 8640 //(int)((float)67.5/ASTEP)
#define ANG_90 11520 //(int)((float)90/ASTEP)
#define ANG_112_5 14400 //(int)((float)112.5/ASTEP)
#define ANG_135 17280 //(int)((float)135/ASTEP)
#define ANG_157_5 20160 //(int)((float)157.5/ASTEP)
#define ANG_180 23040 //(int)((float)180/ASTEP)
#define ANG_202_5 25920 //(int)((float)202.5/ASTEP)
#define ANG_225 28800 //(int)((float)225/ASTEP)
#define ANG_247_5 31680 //(int)((float)247.5/ASTEP)
#define ANG_270 34560 //(int)((float)270/ASTEP)
#define ANG_292_5 37440 //(int)((float)292.5/ASTEP)
#define ANG_315 40320 //(int)((float)225/ASTEP)
#define ANG_337_5 43200 //(int)((float)337.5/ASTEP)
#define ANG_360 46080 //(int)((float)360/ASTEP)
// ------------------------- * ^^^ FINE angles ^^^ * -------------------------
#define FINE2RAD( a ) (((a) * M_PI ) / ANG_180)
#define RAD2FINE( a ) (((a) * ANG_180) / M_PI)
#define FINE2DEG( a ) ((float)(a) / ANG_1) // !@# don't lose precision bits
#define FINE2DEGf( a ) ((a) / (float)ANG_1)
#define DEG2FINE( a ) ((a) * ANG_1)
extern double SinTable[], *CosTable, TanTable[ ANG_360 + 1 ];
extern int XnextTable[ ANG_360 + 1], YnextTable[ ANG_360 + 1 ];
extern int ColumnAngle[640]; //
extern int G_Build_Tables(void);
#define TanDgr( x ) (tan( DEG2RAD( x ) ))
#define SinDgr( x ) (sin( DEG2RAD( x ) ))
#define CosDgr( x ) (cos( DEG2RAD( x ) ))
#define ArcTanDgr( x ) (RAD2DEG( atan( x ) ))
#define ArcSinDgr( x ) (RAD2DEG( asin( x ) ))
#define ArcCosDgr( x ) (RAD2DEG( acos( x ) ))
extern int NormalizeAngle( int angle );
extern int Point2LineDist( int x, int y, int a );
extern int LineLen2Point( int x, int y, int a );
extern quadrant GetQuadrant( float angle );
extern dir4type Get4dir( float angle );
extern dir8type Get8dir( float angle );
extern float TransformPoint( double Point1X, double Point1Y, double Point2X, double Point2Y );
#endif /* __WOLF_MATH_H__ */

View File

@@ -0,0 +1,518 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
/*
* wolf_opengl.c: Wolfenstein3-D OpenGL renderer.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Quake II, and was originally
* written by Id Software, Inc.
*
*/
#include "../wolfiphone.h"
// width and height in 2D
#define WIDTH_2D 640
#define HEIGHT_2D 480
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void GL_SetDefaultState( void )
{
pfglClearColor( 1,0, 0.5 , 0.5 );
pfglCullFace( GL_FRONT );
pfglEnable( GL_TEXTURE_2D );
pfglDisable( GL_DEPTH_TEST );
pfglDisable( GL_CULL_FACE );
pfglDisable( GL_BLEND );
pfglColor4f( 1, 1, 1, 1 );
pfglShadeModel( GL_FLAT );
pfglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawBox( int x, int y, int w, int h, W32 color )
{
pfglDisable( GL_TEXTURE_2D );
// pfglEnable( GL_BLEND );
// pfglBlendFunc( GL_SRC_COLOR, GL_DST_COLOR );
pfglColor4ubv( (GLubyte *) & color );
pfglBegin( GL_QUADS );
pfglVertex2i( x, y );
pfglVertex2i( x, y + h);
pfglVertex2i( x + w, y + h );
pfglVertex2i( x + w, y );
pfglEnd();
pfglColor3f( 1, 1, 1 );
// pfglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// pfglDisable( GL_BLEND );
pfglEnable( GL_TEXTURE_2D );
}
/*
====================
LoadWallTexture
Returns with the texture bound and glColor set to the right intensity.
Loads an image from the filesystem if necessary.
Used both during gameplay and for preloading during level parse.
Wolfenstein was very wasteful with texture usage, making almost half of
the textures just dim versions to provide "lighting" on the different
wall sides. With only a few exceptions for things like the elevator tiles
and outdoor tiles that could only be used in particular orientations
====================
*/
float wallBrightness[1000];
void LoadWallTexture( int wallPicNum ) {
assert( wallPicNum >= 0 && wallPicNum < 1000 );
texture_t *twall = wallTextures[wallPicNum];
if ( !twall ) {
if ( ( wallPicNum & 1 ) &&
wallPicNum != 31 &&
wallPicNum != 41 &&
wallPicNum != 43 &&
wallPicNum != 133 ) {
// this wallPicNum is just a dim version of another image
// load the brighter version
LoadWallTexture( wallPicNum - 1 );
// use the same texture
twall = wallTextures[wallPicNum] = wallTextures[wallPicNum - 1];
// at a dimmer intensity
wallBrightness[wallPicNum] = 0.7f;
} else {
// this wallPicNum has a real image associated with it
char name[1024];
my_snprintf( name, sizeof( name ), "walls/%.3d.tga", wallPicNum );
twall = wallTextures[wallPicNum] = TM_FindTexture( name, TT_Wall );
wallBrightness[wallPicNum] = 1.0f;
}
}
R_Bind( twall->texnum );
// almost half of the walls are just slightly dimmer versions of
// the "bright side", and are not stored as separate textures
float f = wallBrightness[wallPicNum];
pfglColor3f( f, f, f );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
north (y)
__________
| |
west (x) | | east (x)
|________|
south (y)
-----------------------------------------------------------------------------
*/
PUBLIC void R_Draw_Wall( float x, float y, float z1, float z2, int type, int tex )
{
float x1, x2, y1, y2;
switch( type )
{
// X wall
case dir4_east:
x1 = x2 = x + 1;
y1 = -1 - y;
y2 = -y;
break;
case dir4_west:
x1 = x2 = x;
y1 = -y;
y2 = -1 - y;
break;
// Y wall
case dir4_north:
y1 = y2 = -y - 1;
x1 = x;
x2 = x + 1;
break;
case dir4_south:
y1 = y2 = -y;
x1 = x + 1;
x2 = x;
break;
}
LoadWallTexture( tex );
pfglBegin( GL_QUADS );
pfglTexCoord2f( 1.0, 0.0 ); pfglVertex3f( x1, z2, y1 );
pfglTexCoord2f( 0.0, 0.0 ); pfglVertex3f( x2, z2, y2 );
pfglTexCoord2f( 0.0, 1.0 ); pfglVertex3f( x2, z1, y2 );
pfglTexCoord2f( 1.0, 1.0 ); pfglVertex3f( x1, z1, y1 );
pfglEnd();
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_Draw_Door( int x, int y, float z1, float z2, _boolean vertical, _boolean backside, int tex, int amount )
{
float x1, x2, y1, y2, amt;
if( amount == DOOR_FULLOPEN )
{
return;
}
amt = (float)amount / DOOR_FULLOPEN;
if( vertical )
{
x1 = x2 = (float)x + 0.5f;
y1 = -((float)y - amt);
y2 = -((float)y - amt); // -1
if( backside )
{
y1 -= 1;
}
else
{
y2 -= 1;
}
}
else
{
y1 = y2 = -(float)y - 0.5f;
x1 = (float)x + amt; // +1
x2 = (float)x + amt;
if( backside )
{
x2 += 1;
}
else
{
x1 += 1;
}
}
LoadWallTexture( tex );
pfglBegin( GL_QUADS );
pfglTexCoord2f( backside ? 0.0f : 1.0f, 0.0 ); pfglVertex3f( x1, z2, y1 );
pfglTexCoord2f( backside ? 1.0f : 0.0f, 0.0 ); pfglVertex3f( x2, z2, y2 );
pfglTexCoord2f( backside ? 1.0f : 0.0f, 1.0 ); pfglVertex3f( x2, z1, y2 );
pfglTexCoord2f( backside ? 0.0f : 1.0f, 1.0 ); pfglVertex3f( x1, z1, y1 );
pfglEnd();
}
/*
-----------------------------------------------------------------------------
Function: R_DrawSprites -Draws all visible sprites.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawSprites( void )
{
float sina, cosa;
float Ex, Ey, Dx, Dy;
int n_sprt, n, ang;
texture_t *twall;
extern cvar_t *cropSprites;
// build visible sprites list
n_sprt = Sprite_CreateVisList();
if( ! n_sprt )
{
return; // nothing to draw
}
// prepare values for billboarding
ang = NormalizeAngle( Player.position.angle + ANG_90 );
sina = (float)(0.5 * SinTable[ ang ]);
cosa = (float)(0.5 * CosTable[ ang ]);
pfglEnable( GL_BLEND );
qglDepthMask( GL_FALSE );
for( n = 0; n < n_sprt; ++n )
{
int texnum = vislist[ n ].tex;
if( vislist[ n ].dist < MINDIST / 2 )
{
continue; // little hack to save speed & z-buffer
}
assert( texnum >= 0 && texnum < 1000 );
twall = spriteTextures[texnum];
if ( !twall ) {
char name[1024];
my_snprintf( name, sizeof( name ), "%s/%.3d.tga", spritelocation, (vislist[ n ].tex) );
twall = spriteTextures[texnum] = TM_FindTexture( name, TT_Wall );
}
R_Bind( twall->texnum );
pfglBegin( GL_QUADS );
if ( cropSprites->value && twall->header.numBounds > 0 ) {
// draw one or two subrects to avoid blending all the empty space
int b;
for ( b = 0 ; b < twall->header.numBounds ; b++ ) {
// include a bit extra for filtering
float x1 = (float)(twall->header.bounds[b][0][0]-1) / (twall->header.uploadWidth-1);
float y1 = (float)(twall->header.bounds[b][0][1]-1) / (twall->header.uploadHeight-1);
float x2 = (float)(twall->header.bounds[b][1][0]+1) / (twall->header.uploadWidth-1);
float y2 = (float)(twall->header.bounds[b][1][1]+1) / (twall->header.uploadHeight-1);
if ( x1 < 0 ) {
x1 = 0;
} else if ( x2 > 1.0 ) {
x2 = 1.0;
}
if ( y1 < 0 ) {
y1 = 0;
} else if ( y2 > 1.0 ) {
y2 = 1.0;
}
Ex = vislist[ n ].x / FLOATTILE + cosa;
Ey = vislist[ n ].y / FLOATTILE + sina;
pfglTexCoord2f( x1, y1 ); pfglVertex3f( Ex - x1 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y1), -Ey + x1 * 2*sina );
pfglTexCoord2f( x1, y2 ); pfglVertex3f( Ex - x1 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y2), -Ey + x1 * 2*sina );
pfglTexCoord2f( x2, y2 ); pfglVertex3f( Ex - x2 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y2), -Ey + x2 * 2*sina );
pfglTexCoord2f( x2, y1 ); pfglVertex3f( Ex - x2 * 2*cosa, -(LOWERZCOORD + (UPPERZCOORD - LOWERZCOORD) * y1), -Ey + x2 * 2*sina );
}
} else {
Ex = Dx = vislist[ n ].x / FLOATTILE;
Ey = Dy = vislist[ n ].y / FLOATTILE;
Ex += cosa; Ey += sina;
Dx -= cosa; Dy -= sina;
pfglTexCoord2f( 0.0, 0.0 ); pfglVertex3f( Ex, UPPERZCOORD, -Ey );
pfglTexCoord2f( 0.0, 1.0 ); pfglVertex3f( Ex, LOWERZCOORD, -Ey );
pfglTexCoord2f( 1.0, 1.0 ); pfglVertex3f( Dx, LOWERZCOORD, -Dy );
pfglTexCoord2f( 1.0, 0.0 ); pfglVertex3f( Dx, UPPERZCOORD, -Dy );
}
pfglEnd();
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_DrawNumber( int x, int y, int number )
{
texture_t *tex;
int col;
float fcol;
static float w = 0.1f;
int i;
char string[ 20 ];
W32 length;
my_snprintf( string, sizeof( string ), "%d", number );
length = strlen( string );
tex = TM_FindTexture( "pics/N_NUMPIC.tga", TT_Pic );
pfglEnable( GL_TEXTURE_2D );
R_Bind( tex->texnum );
pfglBegin( GL_QUADS );
for( i = length-1 ; i >= 0 ; --i )
{
col = string[ i ] - 48;
fcol = col * w;
pfglTexCoord2f( fcol, 0 ); pfglVertex2i( x, y );
pfglTexCoord2f( fcol+w, 0 ); pfglVertex2i( x+18, y );
pfglTexCoord2f( fcol+w, 1 ); pfglVertex2i( x+18, y+32 );
pfglTexCoord2f( fcol, 1 ); pfglVertex2i( x, y+32 );
x -= 18;
}
pfglEnd();
}
W8 wfont[ ] = {
32, 15, 32, 32, 32, 32, 32, 12, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 };
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_put_line( int x, int y, const char *string )
{
texture_t *tex;
int mx = x;
int num;
float frow, fcol;
static float h = 0.25f; // (32 / 128.0f);
static float w = 0.0625f; // (32 / 512.0f);
tex = TM_FindTexture( "pics/L_FONTPIC.tga", TT_Pic );
R_Bind( tex->texnum );
pfglBegin( GL_QUADS );
while( *string )
{
if( *string == '\n' )
{
mx = x;
y += 32;
++string;
continue;
}
num = *string;
num &= 255;
if( (num & 127) == 32 )
{
mx += 32;
++string;
continue; // space
}
frow = ((num >> 4) - 2) * h;
fcol = (num & 15) * w;
pfglTexCoord2f( fcol, frow ); pfglVertex2i( mx, y );
pfglTexCoord2f( fcol+w, frow ); pfglVertex2i( mx+32, y );
pfglTexCoord2f( fcol+w, frow+h ); pfglVertex2i( mx+32, y+32 );
pfglTexCoord2f( fcol, frow+h ); pfglVertex2i( mx, y+32 );
mx += wfont[ (num & 127) - 32 ];
++string;
}
pfglEnd();
}

View File

@@ -0,0 +1,982 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_player.c: Wolfenstein3-D player management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
player_t Player; // player struct (pos, health etc...)
#define PLAYERSIZE MINDIST // player radius
struct atkinf
{
char tics, attack, frame; // attack is 1 for gun, 2 for knife
} attackinfo[ 4 ][ 14 ] = // 4 guns, 14 frames max for every gun!
{
{ {6,0,1},{6,2,2},{6,0,3},{6,-1,0} },
{ {6,0,1},{6,1,2},{6,0,3},{6,-1,0} },
{ {6,0,1},{6,1,2},{6,3,3},{6,-1,0} },
{ {6,0,1},{6,1,2},{6,4,3},{6,-1,0} },
};
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: true if player can change weapons, otherwise false.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE _boolean PL_ChangeWeapon( player_t *self, int weapon )
{
unsigned itemflag;
itemflag = ITEM_WEAPON_1 << weapon;
if( self->ammo[ AMMO_BULLETS ] == 0 && weapon != WEAPON_KNIFE )
{
// Com_Printf("Not enough ammo.\n");
return false;
}
if( ! (self->items & itemflag) )
{
// Com_Printf( "No weapon.\n" );
return false;
}
self->weapon =
self->pendingweapon = weapon;
self->attackframe =
self->attackcount =
self->weaponframe = 0;
return true;
}
/*
-----------------------------------------------------------------------------
Function: Called if player pressed USE button
Parameters:
Returns: returns true if player used something
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE _boolean PL_Use( player_t *self, LevelData_t *lvl )
{
int x, y, dir;
dir = Get4dir( FINE2RAD( self->position.angle ) );
x = self->tilex + dx4dir[ dir ];
y = self->tiley + dy4dir[ dir ];
if( lvl->tilemap[ x ][ y ] & DOOR_TILE )
{
return Door_TryUse( &lvl->Doors.DoorMap[ x ][ y ], Player.items );
}
if( lvl->tilemap[ x ][ y ] & SECRET_TILE )
{
return PushWall_Push( x, y, dir );
}
if( lvl->tilemap[ x ][ y ] & ELEVATOR_TILE )
{
int newtex;
switch( dir )
{
case dir4_east:
case dir4_west:
newtex = lvl->wall_tex_x[ x ][ y ] += 2;
break;
case dir4_north:
case dir4_south:
return false; // don't allow to press elevator rails
}
if( lvl->tilemap[ self->tilex ][ self->tiley ] & SECRETLEVEL_TILE )
{
self->playstate = ex_secretlevel;
}
else
{
self->playstate = ex_complete;
}
Sound_StartSound( NULL, 0, CHAN_BODY, Sound_RegisterSound( "lsfx/040.wav" ), 1, ATTN_NORM, 0 );
iphoneStartIntermission( 0 );
return true;
}
//Sound_StartSound( NULL, 0, CHAN_BODY, Sound_RegisterSound( "lsfx/020.wav" ), 1, ATTN_NORM, 0 );
return false;
}
#define STOPSPEED 0x0D00
#define FRICTION 0.25f
#define MAXMOVE (MINDIST*2-1)
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: returns true if move ok
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE _boolean PL_TryMove( player_t *self, LevelData_t *lvl )
{
int xl, yl, xh, yh, x, y;
int d, n;
xl = POS2TILE( Player.position.origin[ 0 ] - PLAYERSIZE );
yl = POS2TILE( Player.position.origin[ 1 ] - PLAYERSIZE );
xh = POS2TILE( Player.position.origin[ 0 ] + PLAYERSIZE );
yh = POS2TILE( Player.position.origin[ 1 ] + PLAYERSIZE );
// Cheching for solid walls:
for( y = yl ; y <= yh ; ++y )
for( x = xl ; x <= xh ; ++x )
{
if( lvl->tilemap[ x ][ y ] & SOLID_TILE )
return 0;
if( lvl->tilemap[ x ][ y ] & DOOR_TILE &&
Door_Opened( &lvl->Doors, x, y) != DOOR_FULLOPEN ) {
// iphone hack to allow player to move halfway into door tiles
// if the player bounds doesn't cross the middle of the tile, let the move continue
if ( abs( Player.position.origin[0] - TILE2POS( x ) ) <= 0x9000
&& abs( Player.position.origin[1] - TILE2POS( y ) ) <= 0x9000 ) {
return 0;
}
}
}
// check for actors
for( n = 0 ; n < NumGuards ; ++n )
{
if( Guards[ n ].state >= st_die1 )
continue;
d = self->position.origin[ 0 ] - Guards[ n ].x;
if( d < -MINACTORDIST || d > MINACTORDIST )
continue;
d = self->position.origin[ 1 ] - Guards[ n ].y;
if( d < -MINACTORDIST || d > MINACTORDIST)
continue;
return false;
}
return true;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void PL_ClipMove( player_t *self, int xmove, int ymove )
{
int basex, basey;
basex = self->position.origin[ 0 ];
basey = self->position.origin[ 1 ];
self->position.origin[ 0 ] += xmove;
self->position.origin[ 1 ] += ymove;
if( PL_TryMove( self, r_world ) )
{
return; // we moved as we wanted
}
//Sound_StartSound( NULL, 0, CHAN_BODY, Sound_RegisterSound( "lsfx/000.wav" ), 1, ATTN_NORM, 0 );
if( xmove ) // don't bother if we don't move x!
{
self->position.origin[ 0 ] = basex + xmove;
self->position.origin[ 1 ] = basey;
if( PL_TryMove( self, r_world ) )
{
return; // May be we'll move only X direction?
}
}
if( ymove ) // don't bother if we don't move y!
{
self->position.origin[ 0 ] = basex;
self->position.origin[ 1 ] = basey + ymove;
if( PL_TryMove( self, r_world ) )
{
return; // May be we'll move only Y direction?
}
}
// movement blocked; we must stay on one place... :(
self->position.origin[ 0 ] = basex;
self->position.origin[ 1 ] = basey;
}
/*
-----------------------------------------------------------------------------
Function: Changes player's angle and position
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void PL_ControlMovement( player_t *self, LevelData_t *lvl )
{
int angle, speed;
// rotation
angle = self->position.angle;
// if(cmd->forwardmove || cmd->sidemove)
self->movx = self->movy = 0; // clear accumulated movement
if( Player.cmd.forwardmove )
{
speed = tics * Player.cmd.forwardmove;
self->movx+=(int)(speed * CosTable[ angle ] );
self->movy+=(int)(speed * SinTable[ angle ] );
}
if( Player.cmd.sidemove )
{
speed = tics * Player.cmd.sidemove;
self->movx += (int)( speed * SinTable[ angle ] );
self->movy -= (int)( speed * CosTable[ angle ] );
}
if( ! self->movx && ! self->movy )
return;
#ifdef SPEAR
funnyticount = 0; // ZERO FUNNY COUNTER IF MOVED! // FIXME!
#endif
self->speed = self->movx + self->movy;
// bound movement
if( self->movx > MAXMOVE )
self->movx = MAXMOVE;
else if( self->movx < -MAXMOVE )
self->movx = -MAXMOVE;
if( self->movy > MAXMOVE )
self->movy = MAXMOVE;
else if( self->movy < -MAXMOVE )
self->movy = -MAXMOVE;
// move player and clip movement to walls (check for no-clip mode here)
PL_ClipMove( self, self->movx, self->movy );
self->tilex = POS2TILE( self->position.origin[ 0 ] );
self->tiley = POS2TILE( self->position.origin[ 1 ] );
// pick up items easier -- any tile you touch, instead of
// just the midpoint tile
{
int x, y;
for ( x = -1 ; x <= 1 ; x+= 2 ) {
int tilex = POS2TILE( self->position.origin[0] + x * PLAYERSIZE );
for ( y = -1 ; y <= 1 ; y+= 2 ) {
int tiley = POS2TILE( self->position.origin[1] + y * PLAYERSIZE );
Powerup_PickUp( tilex, tiley );
}
}
}
// Powerup_PickUp( self->tilex, self->tiley );
// Checking for area change, ambush tiles and doors will have negative values
if( lvl->areas[ self->tilex ][ self->tiley ] >= 0 &&
lvl->areas[ self->tilex ][ self->tiley ] != Player.areanumber )
{
Player.areanumber = lvl->areas[ self->tilex ][ self->tiley ];
assert( Player.areanumber >= 0 && Player.areanumber < NUMAREAS );
Areas_ConnectAreas( Player.areanumber );
}
if( lvl->tilemap[ self->tilex ][ self->tiley ] & EXIT_TILE )
{
iphoneStartIntermission( 0 );
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void PL_PlayerAttack( player_t *self, _boolean re_attack )
{
struct atkinf *cur;
self->attackcount -= tics;
while( self->attackcount <= 0 )
{
cur = &attackinfo[ self->weapon ][ self->attackframe ];
switch( cur->attack )
{
case -1:
self->flags &= ~PL_FLAG_ATTCK;
if( ! self->ammo[ AMMO_BULLETS ] )
{
self->weapon = WEAPON_KNIFE;
}
else if( self->weapon != self->pendingweapon )
{
self->weapon = self->pendingweapon;
}
self->attackframe = self->weaponframe = 0;
return;
case 4:
if( ! self->ammo[ AMMO_BULLETS ] )
{
break;
}
if( re_attack )
{
self->attackframe -= 2;
}
case 1:
if( ! self->ammo[ AMMO_BULLETS ] ) // can only happen with chain gun
{
self->attackframe++;
break;
}
fire_lead( self );
self->ammo[ AMMO_BULLETS ]--;
break;
case 2:
fire_hit( self );
break;
case 3:
if(self->ammo[AMMO_BULLETS] && re_attack)
self->attackframe-=2;
break;
}
self->attackcount += cur->tics;
self->attackframe++;
self->weaponframe = attackinfo[ self->weapon ][ self->attackframe ].frame;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_Process( player_t *self, LevelData_t *lvl )
{
int n;
self->madenoise = false;
PL_ControlMovement( self, lvl );
if( self->flags & PL_FLAG_ATTCK )
{
PL_PlayerAttack( self, Player.cmd.buttons & BUTTON_ATTACK );
}
else
{
if( Player.cmd.buttons & BUTTON_USE )
{
if(!(self->flags & PL_FLAG_REUSE) && PL_Use( self, lvl ) )
{
self->flags|=PL_FLAG_REUSE;
}
}
else
{
self->flags &= ~PL_FLAG_REUSE;
}
if( Player.cmd.buttons & BUTTON_ATTACK )
{
self->flags |= PL_FLAG_ATTCK;
self->attackframe = 0;
self->attackcount = attackinfo[ self->weapon ][ 0 ].tics;
self->weaponframe = attackinfo[ self->weapon ][ 0 ].frame;
} else if ( Player.cmd.buttons & BUTTON_CHANGE_WEAPON ) {
self->pendingweapon=self->weapon;
for( n = 0 ; n < 4; ++n )
{
if( ++self->weapon > WEAPON_CHAIN )
{
self->weapon = WEAPON_KNIFE;
}
if( PL_ChangeWeapon( self, self->weapon ) )
{
break;
}
}
self->weapon = self->pendingweapon;
}
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_Reset(void)
{
memset( &Player, 0, sizeof( Player ) );
Player.playstate = ex_notingame;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_Spawn( placeonplane_t location, LevelData_t *lvl )
{
Player.position = location;
Player.tilex = POS2TILE( location.origin[ 0 ] );
Player.tiley = POS2TILE( location.origin[ 1 ] );
Player.areanumber = lvl->areas[ Player.tilex ][ Player.tiley ];
assert( Player.areanumber >= 0 && Player.areanumber < NUMAREAS );
if( Player.areanumber < 0 )
{
Player.areanumber = 36;
}
Areas_ConnectAreas( Player.areanumber );
char str[128];
sprintf( str, "Entering level E%iM%i", currentMap.episode + 1, currentMap.map + 1 );
iphoneSetNotifyText( str );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Cmd_Give_f( void )
{
Com_Printf( "Giving stuff.\n" );
PL_GiveHealth( &Player, 999, 0 );
PL_GiveAmmo( &Player, AMMO_BULLETS, 99 );
PL_GiveWeapon( &Player, WEAPON_AUTO );
PL_GiveWeapon( &Player, WEAPON_CHAIN );
PL_GiveKey( &Player, KEY_GOLD );
PL_GiveKey( &Player, KEY_SILVER );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Cmd_God_f( void )
{
Player.flags ^= FL_GODMODE;
Com_Printf( "God mode %s\n", Player.flags & FL_GODMODE ? "ON":"OFF" );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void PL_notarget_f( void )
{
Player.flags ^= FL_NOTARGET;
Com_Printf( "Notarget mode %s\n", Player.flags & FL_NOTARGET ? "ON":"OFF" );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_Init(void)
{
PL_Reset();
PL_NewGame( &Player );
Cmd_AddCommand( "god", Cmd_God_f );
Cmd_AddCommand( "notarget", PL_notarget_f );
Cmd_AddCommand( "give", Cmd_Give_f );
}
// ------------------------- * environment interraction * -------------------------
#define EXTRAPOINTS 40000 // points for an extra life
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_Damage( player_t *self, entity_t *attacker, int points )
{
if( self->playstate == ex_dead )
{
return;
}
self->LastAttacker = attacker;
if( skill->value == gd_baby )
{
points >>= 2;
}
// vibe the phone
SysIPhoneVibrate();
// note the direction of the last hit for the directional blends
{
int dx = attacker->x - self->position.origin[0];
int dy = attacker->y - self->position.origin[1];
// probably won't ever have damage from self, but check anyway
if ( dx != 0 || dy != 0 ) {
float angle = atan2f( dy, dx );
float playerAngle = self->position.angle * 360.0f / (float)ANG_360;
float deltaAngle;
angle = angle * 180.0f / M_PI;
if ( angle < 0 ) {
angle = 360 + angle;
}
deltaAngle = angle - playerAngle;
if ( deltaAngle > 180 ) {
deltaAngle = deltaAngle - 360;
}
if ( deltaAngle < -180 ) {
deltaAngle = 360 + deltaAngle;
}
// Com_Printf( "damage: player angle: %4.0f shotAngle: %4.0f deltaAngle:%4.0f\n", playerAngle, angle, deltaAngle );
if ( deltaAngle > 40 ) {
iphoneSetAttackDirection( 1 );
} else if ( deltaAngle < -40 ) {
iphoneSetAttackDirection( -1 );
}
}
}
// do everything else but subtract health in god mode, to ease
// testing of damage feedback
if( !(self->flags & FL_GODMODE) )
{
self->health -= points;
}
if( self->health <= 0 )
{
// dead
self->health = 0;
self->playstate = ex_dead;
Sound_StartSound( NULL, 0, CHAN_BODY, Sound_RegisterSound( "lsfx/009.wav" ), 1, ATTN_NORM, 0 );
}
// red screen flash
iphoneStartDamageFlash( points );
// stop the happy grin face if shot before it times out
Player.face_gotgun = false;
// make BJ's eyes bulge on huge hits
if( points > 30 && Player.health != 0 )
{
Player.face_ouch = true;
Player.facecount = 0;
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: returns true if player needs this health.
Notes:
gives player some HP
max can be:
0 - natural player's health limit (100 or 150 with augment)
>0 - indicates the limit
-----------------------------------------------------------------------------
*/
PUBLIC _boolean PL_GiveHealth( player_t *self, int points, int max )
{
if( max == 0 )
{
max = (self->items & ITEM_AUGMENT) ? 150 : 100;
}
if( self->health >= max )
{
return false; // doesn't need this health
}
self->health += points;
if( self->health > max )
{
self->health = max;
}
Player.face_gotgun = false;
return true; // took it
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: returns true if player needs this ammo
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC _boolean PL_GiveAmmo( player_t *self, int type, int ammo )
{
int max_ammo[ AMMO_TYPES ] = { 99 };
int max;
max = max_ammo[ type ];
if( self->items & ITEM_BACKPACK )
{
max *= 2;
}
if( self->ammo[ type ] >= max )
{
return false; // don't need
}
if( ! self->ammo[ type ] && ! self->attackframe ) // knife was out
{
self->weapon = self->pendingweapon;
}
self->ammo[ type ] += ammo;
if( self->ammo[ type ] > max )
{
self->ammo[ type ] = max;
}
return true;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_GiveWeapon( player_t *self, int weapon )
{
unsigned itemflag;
PL_GiveAmmo( self, AMMO_BULLETS, 6 ); // give some ammo with a weapon
itemflag = ITEM_WEAPON_1 << weapon;
if( self->items & itemflag )
{
return; // player owns this weapon
}
else
{
self->items |= itemflag;
if ( self->weapon < weapon ) { // don't switch if already using better weapon
self->weapon = self->pendingweapon = weapon;
}
}
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_GivePoints( player_t *self, W32 points )
{
#if 0 // no score on iphone
self->score += points;
while( self->score >= self->next_extra )
{
self->next_extra += EXTRAPOINTS;
PL_GiveLife( self );
}
#endif
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_GiveKey( player_t *self, int key )
{
self->items |= ITEM_KEY_1 << key;
}
/*
-----------------------------------------------------------------------------
Function: Set up player for the new game
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_NewGame( player_t *self )
{
memset( self, 0, sizeof( player_t ) );
self->health = 100;
self->ammo[ AMMO_BULLETS ] = 16; // JDC: changed for iphone 8;
self->lives = 3;
self->weapon = self->pendingweapon = WEAPON_PISTOL;
self->items = ITEM_WEAPON_1 | ITEM_WEAPON_2;
self->next_extra = EXTRAPOINTS;
}
/*
-----------------------------------------------------------------------------
Function: Set up player for level transition
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PL_NextLevel( player_t *self )
{
self->old_score = self->score;
self->attackcount = self->attackframe = self->weaponframe = 0;
self->flags = 0;
self->items &= ~(ITEM_KEY_1 | ITEM_KEY_2 | ITEM_KEY_3 | ITEM_KEY_4);
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: self -[in] Player to respawn in game world.
Returns: returns false if no lives left
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC _boolean PL_Reborn( player_t *self )
{
#if 0 // removed game over from iphone version
if( --self->lives < 1 )
{
return false;
}
#endif
self->health = 100;
self->ammo[ AMMO_BULLETS ] = 16; // JDC: changed for iphone 8;
self->score = self->old_score;
self->attackcount = 0;
self->attackframe = 0;
self->weaponframe = 0;
self->flags = 0;
self->weapon = self->pendingweapon = WEAPON_PISTOL;
self->items = ITEM_WEAPON_1 | ITEM_WEAPON_2;
self->playstate = ex_playing;
return true;
}

View File

@@ -0,0 +1,179 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_player.h: Wolfenstein3-D player management.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
/*
Notes:
This module is implemented by wolf_player.c
*/
#ifndef __WOLF_PLAYER_H__
#define __WOLF_PLAYER_H__
#define ITEM_KEY_1 1
#define ITEM_KEY_2 2
#define ITEM_KEY_3 4
#define ITEM_KEY_4 8
#define ITEM_WEAPON_1 16
#define ITEM_WEAPON_2 32
#define ITEM_WEAPON_3 64
#define ITEM_WEAPON_4 128
#define ITEM_WEAPON_5 256
#define ITEM_WEAPON_6 512
#define ITEM_WEAPON_7 1024
#define ITEM_WEAPON_8 2048
#define ITEM_BACKPACK (1<<12) // doubles carrying capacity
#define ITEM_AUGMENT (1<<13) // adds 50 to maximum health
#define ITEM_UNIFORM (1<<14) // allows you to pass guards
#define ITEM_AUTOMAP (1<<15) // shows unknown map ares in other color (as in DooM)
#define ITEM_FREE (1<<16) // - unused -
enum weapon_e
{
WEAPON_KNIFE,
WEAPON_PISTOL,
WEAPON_AUTO,
WEAPON_CHAIN,
WEAPON_TYPES
};
enum key_e
{
KEY_GOLD,
KEY_SILVER,
KEY_FREE1,
KEY_FREE2,
KEY_TYPES
};
enum ammo_e
{
AMMO_BULLETS,
AMMO_TYPES
};
// flags
#define PL_FLAG_REUSE 1 // use button pressed
#define PL_FLAG_ATTCK 2 // attacking
// debug (cheat codes) flags
#define FL_GODMODE (1<<4)
#define FL_NOTARGET (1<<6)
typedef enum state_e
{
ex_notingame,
ex_playing,
ex_dead,
ex_secretlevel,
ex_victory,
ex_complete
/*
ex_stillplaying,
ex_completed,
ex_died,
ex_warped,
ex_resetgame,
ex_loadedgame,
ex_victorious,
ex_abort,
ex_demodone,
ex_secretlevel
*/
} state_t;
// ------------------------- * types * -------------------------
// Player structure: Holds all info about player
typedef struct player_s
{
usercmd_t cmd; // movement / action command
placeonplane_t position; // player position
int movx, movy, speed;
int tilex, tiley;
// stats
int health, lives, frags;
int armor; // there are 2 types. The better one is indicated by high bit set
int ammo[AMMO_TYPES];
int old_score, score, next_extra;
unsigned items; // (keys, weapon)
int weapon, pendingweapon;
// additional info
int attackframe, attackcount, weaponframe; // attack info
unsigned flags;
int areanumber;
_boolean madenoise; // FIXME: move to flags?
entity_t *LastAttacker;
int faceframe, facecount; // bj's face in the HUD // FIXME decide something!
_boolean face_gotgun, face_ouch;
state_t playstate; // fixme: move to gamestate
} player_t;
extern player_t Player;
extern void PL_Spawn( placeonplane_t location, LevelData_t *lvl );
extern void PL_Process( player_t *self, LevelData_t *lvl );
extern void PL_Damage( player_t *self, entity_t *attacker, int points );
extern _boolean PL_GiveHealth( player_t *self, int points, int max );
extern _boolean PL_GiveAmmo( player_t *self, int type, int ammo );
extern void PL_GiveWeapon( player_t *self, int weapon );
extern void PL_GivePoints( player_t *self, W32 points );
extern void PL_GiveKey( player_t *self, int key );
extern void PL_NewGame( player_t *self );
extern void PL_NextLevel( player_t *self );
extern _boolean PL_Reborn( player_t *self );
extern void PL_Init( void );
extern void PL_Reset( void );
extern void fire_hit( player_t *self );
extern void fire_lead( player_t *self );
#endif /* __WOLF_PLAYER_H__ */

View File

@@ -0,0 +1,385 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2001 by DarkOne the Hacker
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.
*/
/*
* wolf_pushwalls.c: Wolfenstein3-D power-up handler.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
int Pow_Texture[ pow_last ] =
{
SPR_STAT_34, // pow_gibs
SPR_STAT_38, // pow_gibs2
SPR_STAT_6, // pow_alpo
SPR_STAT_25, // pow_firstaid
SPR_STAT_20, // pow_key1
SPR_STAT_21, // pow_key2
// not used
SPR_STAT_20, // pow_key3
SPR_STAT_20, // pow_key4
SPR_STAT_29, // pow_cross
SPR_STAT_30, // pow_chalice
SPR_STAT_31, // pow_bible
SPR_STAT_32, // pow_crown
SPR_STAT_26, // pow_clip
SPR_STAT_26, // pow_clip2
SPR_STAT_27, // pow_machinegun
SPR_STAT_28, // pow_chaingun
SPR_STAT_24, // pow_food
SPR_STAT_33, // pow_fullheal
// spear
SPR_STAT_49, // pow_25clip
SPR_STAT_51, // pow_spear
};
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void Pow_Remove( powerup_t *powerup )
{
powerup->x = -1;
powerup->y = -1;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE powerup_t *Pow_AddNew( void )
{
for ( int i = 0 ; i < levelData.numPowerups ; i++ ) {
if ( levelData.powerups[i].x == -1 ) {
return &levelData.powerups[i];
}
}
if ( levelData.numPowerups == MAX_POWERUPS ) {
return &levelData.powerups[0];
}
levelData.numPowerups++;
return &levelData.powerups[levelData.numPowerups-1];
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Powerup_Reset( void )
{
levelData.numPowerups = 0;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns: 1 if powerup is picked up, otherwise 0.
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE int Pow_Give( pow_t type )
{
static const char *keynames[] = { "Gold", "Silver", "?", "?" };
switch( type )
{
//
// Keys
//
case pow_key1:
case pow_key2:
case pow_key3:
case pow_key4:
type -= pow_key1;
PL_GiveKey( &Player, type );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/012.wav" ), 1, ATTN_NORM, 0 );
iphoneSetNotifyText( "%s key\n", keynames[ type ] );
break;
//
// Treasure
//
case pow_cross:
PL_GiveHealth( &Player, 1, 150 ); // iphone -- trasure acts as health crumbs
PL_GivePoints( &Player, 100 );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/035.wav" ), 1, ATTN_NORM, 0 );
if ( ++levelstate.found_treasure == levelstate.total_treasure ) {
iphoneSetNotifyText( "You found the last treasure!" );
}
break;
case pow_chalice:
PL_GiveHealth( &Player, 1, 150 ); // iphone -- trasure acts as health crumbs
PL_GivePoints( &Player, 500 );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/036.wav" ), 1, ATTN_NORM, 0 );
if ( ++levelstate.found_treasure == levelstate.total_treasure ) {
iphoneSetNotifyText( "You found the last treasure!" );
}
break;
case pow_bible:
PL_GiveHealth( &Player, 1, 150 ); // iphone -- trasure acts as health crumbs
PL_GivePoints( &Player, 1000 );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/037.wav" ), 1, ATTN_NORM, 0 );
if ( ++levelstate.found_treasure == levelstate.total_treasure ) {
iphoneSetNotifyText( "You found the last treasure!" );
}
break;
case pow_crown:
PL_GiveHealth( &Player, 1, 150 ); // iphone -- trasure acts as health crumbs
PL_GivePoints( &Player, 5000 );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/045.wav" ), 1, ATTN_NORM, 0 );
if ( ++levelstate.found_treasure == levelstate.total_treasure ) {
iphoneSetNotifyText( "You found the last treasure!" );
}
break;
//
// Health
//
case pow_gibs:
if( ! PL_GiveHealth( &Player, 1, 11 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/061.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_alpo:
if( ! PL_GiveHealth( &Player, 4, 0 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/033.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_food:
if( ! PL_GiveHealth( &Player, 10, 0 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/033.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_firstaid:
if( ! PL_GiveHealth( &Player, 25, 0 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/034.wav" ), 1, ATTN_NORM, 0 );
break;
//
// Weapon & Ammo
//
case pow_clip:
if( ! PL_GiveAmmo( &Player, AMMO_BULLETS, 8 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/031.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_clip2:
if( ! PL_GiveAmmo( &Player, AMMO_BULLETS, 4 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/031.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_25clip:
if( ! PL_GiveAmmo( &Player, AMMO_BULLETS, 25 ) )
{
return 0;
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/064.wav" ), 1, ATTN_NORM, 0 );
break;
case pow_machinegun:
PL_GiveWeapon( &Player, WEAPON_AUTO );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/030.wav" ), 1, ATTN_NORM, 0 );
iphoneSetNotifyText( "Machinegun" );
break;
case pow_chaingun:
PL_GiveWeapon( &Player, WEAPON_CHAIN );
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/038.wav" ), 1, ATTN_NORM, 0 );
iphoneSetNotifyText( "Chaingun" );
Player.facecount = -100;
Player.face_gotgun = true;
break;
//
// Artifacts
//
case pow_fullheal:
// go to 150 health
PL_GiveHealth( &Player, 150, 150 );
PL_GiveAmmo( &Player, AMMO_BULLETS, 25 );
if ( ++levelstate.found_treasure == levelstate.total_treasure ) {
iphoneSetNotifyText( "You found the last treasure!" );
} else {
iphoneSetNotifyText( "Full Heal" );
}
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "lsfx/034.wav" ), 1, ATTN_NORM, 0 );
// no extra lives on iPhone Com_Printf( "Extra life!\n" );
break;
case pow_spear:
{
char szTextMsg[ 256 ];
Sound_StartSound( NULL, 0, CHAN_ITEM, Sound_RegisterSound( "sodsfx/109.wav" ), 1, ATTN_NORM, 0 );
iphoneSetNotifyText( "Spear of Destiny" );
my_snprintf( szTextMsg, sizeof( szTextMsg ),
"loading ; map s%.2d.map\n", 20 );
Cbuf_AddText( szTextMsg );
}
break;
default:
Com_DPrintf( "Warning: Unknown item type: %d\n", type );
break;
}
iphoneStartBonusFlash();
return 1;
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: x, y -[in] In are in TILES.
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Powerup_Spawn( int x, int y, int type )
{
powerup_t *newp;
levelData.tilemap[ x ][ y ] |= POWERUP_TILE;
newp = Pow_AddNew();
newp->sprite = Sprite_GetNewSprite();
Sprite_SetPos( newp->sprite, TILE2POS( newp->x = x ), TILE2POS( newp->y = y ), 0 );
newp->type = type;
Sprite_SetTex( newp->sprite, -1, Pow_Texture[ type ] );
levelData.tilemap[ x ][ y ] |= POWERUP_TILE;
// good place to update total treasure count!
}
/*
-----------------------------------------------------------------------------
Function:
Parameters: x, y -[in] In are in TILES.
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Powerup_PickUp( int x, int y )
{
int i;
powerup_t *pow;
_boolean p_left = false, p_pick = false;
for ( i = 0, pow = levelData.powerups ; i < levelData.numPowerups ; i++, pow++ ) {
if( pow->x == x && pow->y == y)
{// got a powerup here
if( Pow_Give( pow->type ) ) //FIXME script
{// picked up this stuff, remove it!
p_pick = true;
Sprite_RemoveSprite( pow->sprite );
Pow_Remove( pow );
}
else
{// player do not need it, so may be next time!
p_left = true;
}
}
}
if( p_left )
{
levelData.tilemap[ x ][ y ] |= POWERUP_TILE;
}
else
{
levelData.tilemap[ x ][ y ] &= ~POWERUP_TILE;
}
}

View File

@@ -0,0 +1,85 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_powerups.h: Wolfenstein3-D power-up handler.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
/*
Notes:
This module is implemented by wolf_powerups.c
*/
#ifndef __WOLF_POWERUPS_H__
#define __WOLF_POWERUPS_H__
typedef enum
{
//please provide description
pow_gibs, // 1% if <=10%; SLURPIESND
pow_gibs2, // 1% if <=10%; SLURPIESND
pow_alpo, // 4% if <100%; HEALTH1SND
pow_firstaid, // 25% if <100%; HEALTH2SND
pow_key1, // gold key; GETKEYSND
pow_key2, // silver key; GETKEYSND
pow_key3, // not used
pow_key4, // not used
pow_cross, // 100pts; BONUS1SND
pow_chalice, // 500pts; BONUS2SND
pow_bible, // 1000pts; BONUS3SND
pow_crown, // 5000pts; BONUS4SND
pow_clip, // 8bul if <99bul; GETAMMOSND
pow_clip2, // 4bul if <99bul; GETAMMOSND
pow_machinegun, // machine gun; GETMACHINESND
pow_chaingun, // gatling gun; GETGATLINGSND
pow_food, // 10% if <100%; HEALTH1SND
pow_fullheal, // 99%, 25bul; BONUS1UPSND
pow_25clip, // 25bul if <99bul; GETAMMOBOXSND
pow_spear, // spear of destiny!
pow_last
// add new types <!only!> here (after last)
} pow_t;
typedef struct powerup_s
{
int x, y;
pow_t type;
int sprite;
} powerup_t;
extern void Powerup_Reset( void );
extern void Powerup_Spawn( int x, int y, int type );
extern void Powerup_PickUp( int x, int y );
#endif /* __WOLF_POWERUPS_H__ */

View File

@@ -0,0 +1,175 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_pushwalls.c: Wolfenstein3-D push-wall handler.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
Pwall_t PWall;
/*
-----------------------------------------------------------------------------
Function: PushWall_Reset() -Reset pushwall status.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PushWall_Reset(void)
{
memset( &PWall, 0, sizeof( Pwall_t ) );
}
/*
-----------------------------------------------------------------------------
Function: PushWall_Push() -Try to move push-wall.
Parameters: x, y -[in] Coordinates in tilemap.
dir -[in] Direction in which push-wall is intended to move.
Returns: true if push successful, otherwise false.
Notes: Called whenever someone tries to push a secret wall.
-----------------------------------------------------------------------------
*/
PUBLIC _boolean PushWall_Push( int x, int y, dir4type dir )
{
int dx, dy;
if( PWall.active )
{
return false; // another PWall is moving [only one at a time!]
}
dx = dx4dir[ dir ];
dy = dy4dir[ dir ];
if( r_world->tilemap[ x + dx ][ y + dy ] & (SOLID_TILE | DOOR_TILE) )
{ // noway (smth is blocking)
return true;
}
// remove secret flag & make everything needed when pushwall used!
r_world->tilemap[ x ][ y ] &= (~SECRET_TILE);
r_world->tilemap[ x ][ y ] &= (~WALL_TILE);
r_world->tilemap[ x ][ y ] |= PUSHWALL_TILE;
if ( ++levelstate.found_secrets == levelstate.total_secrets ) {
iphoneSetNotifyText( "You found the last secret!" );
} else {
iphoneSetNotifyText( "You found a secret!" );
}
if( g_version->value == SPEAROFDESTINY )
{
Sound_StartSound( NULL, 1, CHAN_AUTO, Sound_RegisterSound( "sfx/030.wav" ), 1, ATTN_STATIC, 0 );
}
else
{
Sound_StartSound( NULL, 1, CHAN_AUTO, Sound_RegisterSound( "sfx/034.wav" ), 1, ATTN_STATIC, 0 );
}
// good way to avoid stuckness; [un]comment one more down!
// it makes a tile behind pushwall unpassable
r_world->tilemap[ x + dx ][ y + dy ] |= PUSHWALL_TILE;
r_world->wall_tex_x[ x + dx ][ y + dy ] = r_world->wall_tex_x[ x ][ y ];
r_world->wall_tex_y[ x + dx ][ y + dy ] = r_world->wall_tex_y[ x ][ y ];
// write down PWall info
PWall.active = true;
PWall.PWtilesmoved = PWall.PWpointsmoved = 0;
PWall.dir = dir;
PWall.x = x; PWall.y = y;
PWall.dx = dx; PWall.dy = dy;
PWall.tex_x = r_world->wall_tex_x[ x ][ y ];
PWall.tex_y = r_world->wall_tex_y[ x ][ y ];
return true;
}
/*
-----------------------------------------------------------------------------
Function: PushWall_Process() -Process push-walls.
Parameters: Nothing.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void PushWall_Process( void )
{
if( ! PWall.active )
{
return; // no active PWall to work with
}
PWall.PWpointsmoved += tics;
if( PWall.PWpointsmoved < 128 )
{
return;
}
PWall.PWpointsmoved -= 128;
PWall.PWtilesmoved++;
// Free tile
r_world->tilemap[ PWall.x ][ PWall.y ] &= (~PUSHWALL_TILE);
// Occupy new tile
PWall.x += PWall.dx;
PWall.y += PWall.dy;
// Shall we move further?
if( r_world->tilemap[ PWall.x + PWall.dx ][ PWall.y + PWall.dy ] & (SOLID_TILE | DOOR_TILE | ACTOR_TILE | POWERUP_TILE) ||
PWall.PWtilesmoved == 3 )
{
r_world->tilemap[ PWall.x ][ PWall.y ] &= (~PUSHWALL_TILE); // wall now
r_world->tilemap[ PWall.x ][ PWall.y ] |= WALL_TILE; // wall now
r_world->wall_tex_x[ PWall.x ][ PWall.y ] = PWall.tex_x;
r_world->wall_tex_y[ PWall.x ][ PWall.y ] = PWall.tex_y;
PWall.active = false; // Free Push Wall
}
else
{
r_world->tilemap[ PWall.x + PWall.dx ][ PWall.y + PWall.dy ] |= PUSHWALL_TILE;
}
}

View File

@@ -0,0 +1,373 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_raycast.c: Wolfenstein3-D ray-casting.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
W8 tile_visible[ 64 ][ 64 ]; // can player see this tile?
/*
-----------------------------------------------------------------------------
Function: R_RayCast() -Ray cast viewport.
Parameters: viewport -[in] Position of camera.
lvl -[in] Pointer to valid LevelData_t structure.
Returns: Nothing.
Notes: Marks all visible tiles in tile_visible[] array.
-----------------------------------------------------------------------------
*/
PUBLIC void R_RayCast( placeonplane_t viewport, LevelData_t *lvl )
{
int n, x, y, angle, vx, vy;
r_trace_t trace;
memset( tile_visible, 0, sizeof( tile_visible ) ); // clear tile visible flags
// viewport tile coordinates
x = viewport.origin[ 0 ];
y = viewport.origin[ 1 ];
angle = viewport.angle;
vx = POS2TILE( viewport.origin[ 0 ] );
vy = POS2TILE( viewport.origin[ 1 ] );
trace.tile_vis = tile_visible;
trace.flags = TRACE_SIGHT | TRACE_MARK_MAP;
//
// Ray casting
//
// FIXME: control ray count and make angle init
for( n = 0 ; n < 640 ; ++n )
{
trace.x = x;
trace.y = y;
trace.a = NormalizeAngle( angle + ColumnAngle[ n ] );
R_Trace( &trace, lvl );
}
//
// Rendering
//
for( x = 0 ; x < 64; ++x )
for( y = 0 ; y < 64; ++y )
if( tile_visible[ x ][ y ] )
{
lvl->tileEverVisible[x][y] = 1; // for automap
if( lvl->tilemap[ x ][ y ] & DOOR_TILE )
{
/* door */
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_open )
{
_boolean backside = false;
if( lvl->Doors.DoorMap[ x ][ y ].vertical )
{
if( x < vx )
backside = true;
}
else
{
if( y < vy )
backside = true;
}
R_Draw_Door( x, y, LOWERZCOORD, UPPERZCOORD,
lvl->Doors.DoorMap[ x ][ y ].vertical,
backside,
lvl->Doors.DoorMap[ x ][ y ].texture,
Door_Opened( &lvl->Doors, x, y ) );
}
/* door sides */
if( lvl->Doors.DoorMap[ x ][ y ].vertical )
{
if( y <= vy )
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, TEX_PLATE );
if( y >= vy )
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, TEX_PLATE );
if( x <= vx && lvl->tilemap[ x - 1 ][ y ] & WALL_TILE )
R_Draw_Wall( (float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, lvl->wall_tex_x[ x - 1 ][ y ] );
if( x >= vx && lvl->tilemap[ x + 1 ][ y ] & WALL_TILE )
R_Draw_Wall( (float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, lvl->wall_tex_x[ x + 1 ][ y ] );
}
else
{
if( x <= vx )
R_Draw_Wall((float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, TEX_PLATE+1);
if( x >= vx )
R_Draw_Wall((float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, TEX_PLATE+1);
if( y <= vy && lvl->tilemap[ x ][ y - 1 ] & WALL_TILE )
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, lvl->wall_tex_y[x][y-1]);
if( y >= vy && lvl->tilemap[ x ][ y + 1 ] & WALL_TILE )
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, lvl->wall_tex_y[x][y+1]);
}
}
else
{
/* Push-Wall */
if( (r_world->tilemap[ x ][ y ] & PUSHWALL_TILE) )
{
float dx, dy;
dx = PWall.dx * PWall.PWpointsmoved / 128.0f;
dy = PWall.dy * PWall.PWpointsmoved / 128.0f;
if( PWall.x <= vx )
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_east, PWall.tex_x );
if( PWall.x >= vx )
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_west, PWall.tex_x );
if( PWall.y <= vy )
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_north, PWall.tex_y );
if( PWall.y >= vy )
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_south, PWall.tex_y );
}
/* x-wall */
if( x <= vx && r_world->tilemap[ x - 1 ][ y ] & WALL_TILE )
R_Draw_Wall( (float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, r_world->wall_tex_x[x-1][y]);
if( x >= vx && r_world->tilemap[ x + 1 ][ y ] & WALL_TILE )
R_Draw_Wall( (float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, r_world->wall_tex_x[x+1][y]);
/* y-wall */
if( y <= vy && r_world->tilemap[ x ][ y - 1 ] & WALL_TILE )
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, r_world->wall_tex_y[x][y-1]);
if( y >= vy && r_world->tilemap[ x ][ y + 1 ] & WALL_TILE )
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, r_world->wall_tex_y[x][y+1]);
}
}
// back to full brightness in case the last draw was a dim wall
pfglColor3f( 1, 1, 1 );
}
int x_tile_step[ 4 ] = { 1, -1, -1, 1 };
int y_tile_step[ 4 ] = { 1, 1, -1, -1 };
/*
-----------------------------------------------------------------------------
Function: R_TraceCheck() -Trace ray check.
Parameters:
lvl -[in] Pointer to valid LevelData_t structure.
x, y -[in] In tiles.
Returns: true to stop tracing, false otherwise.
Notes: Tells ray casting if we hit a wall or door and to stop tracing.
-----------------------------------------------------------------------------
*/
PRIVATE _boolean R_TraceCheck( LevelData_t *lvl, int x, int y, int frac, int dfrac, _boolean vert, _boolean flip, r_trace_t *trace )
{
if( lvl->tilemap[ x ][ y ] & WALL_TILE )
{
if( vert )
{
trace->x = (x << TILESHIFT) + (flip ? TILEGLOBAL : 0);
trace->y = (y << TILESHIFT) + frac;
trace->flags |= TRACE_HIT_VERT;
}
else
{
trace->x = (x << TILESHIFT) + frac;
trace->y = (y << TILESHIFT) + (flip ? TILEGLOBAL : 0);
trace->flags &= ~TRACE_HIT_VERT;
}
return true; // wall, stop tracing
}
if( trace->tile_vis )
{
trace->tile_vis[ x ][ y ] = true; // this tile is visible
}
if( lvl->tilemap[ x ][ y ] & DOOR_TILE &&
lvl->Doors.DoorMap[ x ][ y ].action != dr_open )
{
frac += dfrac >> 1;
if( POS2TILE( frac ) )
return false;
if( vert )
{
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_closed &&
(frac >> 10) > DOOR_FULLOPEN - Door_Opened( &lvl->Doors, x, y ) )
{
return false; // opened enough
}
trace->x = TILE2POS( x );
trace->y = (y << TILESHIFT) + frac;
trace->flags |= TRACE_HIT_VERT;
}
else
{
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_closed &&
(frac >> 10) < Door_Opened( &lvl->Doors, x, y ) )
{
return false; // opened enough
}
trace->y = TILE2POS( y );
trace->x = (x << TILESHIFT) + frac;
trace->flags &= ~TRACE_HIT_VERT;
}
trace->flags |= TRACE_HIT_DOOR;
return true; // closed door, stop tracing
}
return false; // no intersection, go on!
}
/*
-----------------------------------------------------------------------------
Function: R_Trace() -Trace ray.
Parameters:
trace -[in] Pointer to valid r_trace_t structure.
lvl -[in] Pointer to valid LevelData_t structure.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_Trace( r_trace_t *trace, LevelData_t *lvl )
{
int xtilestep, ytilestep;
int xstep, ystep;
int xtile, ytile;
int xintercept, yintercept;
int YmapPos, XmapPos;
quadrant q;
// Setup for ray casting
q = GetQuadrant( FINE2RAD( trace->a ) );
xtilestep = x_tile_step[ q ];
ytilestep = y_tile_step[ q ];
xtile = POS2TILE( trace->x ) + xtilestep;
ytile = POS2TILE( trace->y ) + ytilestep;
xstep = ytilestep * XnextTable[ trace->a ];
ystep = xtilestep * YnextTable[ trace->a ];
xintercept = (int)( ( ((ytilestep == -1 ? ytile+1 : ytile) << TILESHIFT) - trace->y ) / TanTable[ trace->a ]) + trace->x;
yintercept = (int)( ( ((xtilestep == -1 ? xtile+1 : xtile) << TILESHIFT) - trace->x ) * TanTable[ trace->a ]) + trace->y;
YmapPos = yintercept >> TILESHIFT; // toXray
XmapPos = xintercept >> TILESHIFT; // toYray
if( trace->tile_vis )
{
// this tile is visible
trace->tile_vis[ POS2TILE( trace->x ) ][ POS2TILE( trace->y ) ] = true;
}
//
// Start of ray-casting
//
while( 1 )
{
//
// Vertical loop // an anologue for X-Ray
//
while( ! (ytilestep == -1 && YmapPos <= ytile) && ! (ytilestep == 1 && YmapPos >= ytile) )
{
if( xtile < 0 || xtile >= 64 || YmapPos < 0 || YmapPos >= 64 )
{
return;
}
if( R_TraceCheck( lvl, xtile, YmapPos, yintercept % TILEGLOBAL, ystep, true, (_boolean)(xtilestep == -1), trace ) )
{
return;
}
// prepare for next step
xtile += xtilestep;
yintercept += ystep;
YmapPos = yintercept >> TILESHIFT;
}
//
// Horizontal loop // an anologue for Y-Ray
//
while( ! (xtilestep == -1 && XmapPos <= xtile) && ! (xtilestep == 1 && XmapPos >= xtile) )
{
if( ytile < 0 || ytile >= 64 || XmapPos < 0 || XmapPos >= 64 )
{
return;
}
if( R_TraceCheck( lvl, XmapPos, ytile, xintercept % TILEGLOBAL, xstep, false, (_boolean)(ytilestep == -1), trace ) )
{
return;
}
// prepare for next step
ytile += ytilestep;
xintercept += xstep;
XmapPos = xintercept >> TILESHIFT;
}
} // end of while( 1 )
}

View File

@@ -0,0 +1,74 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_raycast.h: Wolfenstein3-D ray-casting.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
/*
Notes:
This module is implemented by wolf_raycast.c
*/
#ifndef __WOLF_RAYCAST_H__
#define __WOLF_RAYCAST_H__
// marks
#define TRACE_MARK_MAP 1 // marks traced area in 'AM_AutoMap.vis' array
// obstacle levels
#define TRACE_SIGHT 2 // player sight
#define TRACE_SIGHT_AI 4 // enemy sight
#define TRACE_BULLET 8 // bullet
#define TRACE_OBJECT 16 // object
#define TRACE_HIT_VERT 32 // vertical wall was hit
#define TRACE_HIT_DOOR 64 // door was hit
#define TRACE_HIT_PWALL 128 // pushwall was hit
typedef struct r_trace_s
{
int x, y; // origin
int a; // trace angle
int flags;
W8 (*tile_vis)[ 64 ]; // should point to [ 64 ][ 64 ] array
} r_trace_t;
#define UPPERZCOORD 0.6f
#define LOWERZCOORD -0.6f
extern W8 tile_visible[ 64 ][ 64 ]; // can player see this tile?
extern void R_RayCast( placeonplane_t viewport, LevelData_t *lvl );
extern void R_Trace( r_trace_t *trace, LevelData_t *lvl );
#endif /* __WOLF_RAYCAST_H__ */

View File

@@ -0,0 +1,96 @@
/*
Copyright (C) 2004-2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
/*
* wolf_renderer.c: Wolfenstein 3-D renderer.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
*
* Acknowledgement:
* Portion of this code was derived from Quake II, and was originally
* written by Id Software, Inc.
*
*/
#include "../wolfiphone.h"
LevelData_t *r_world;
/*
-----------------------------------------------------------------------------
Function: R_BeginRegistration -Start the rendering registration sequence.
Parameters: map -[in] The name of the map to load.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void R_BeginRegistration( const char *map )
{
char fullname[ MAX_GAMEPATH ];
if( ! map || ! *map )
{
return;
}
++texture_registration_sequence;
my_snprintf( fullname, sizeof( fullname ), "maps/%s.map", map );
// Door_ResetDoors( &r_world->Doors );
Powerup_Reset();
Sprite_Reset();
Areas_InitAreas( Player.areanumber );
PushWall_Reset();
memset( &levelstate, 0, sizeof( levelstate ) ); // Reset gamestate
ResetGuards();
r_world = Level_LoadMap( fullname );
if( r_world == NULL )
{
Com_Printf( "Could not load map (%s)\n", map );
return;
}
levelstate.floornum = floornumber;
if( g_version->value == SPEAROFDESTINY )
{
if( strlen( map ) >= 2 )
{
levelstate.floornum = atoi( map+1 );
if( levelstate.floornum == 20 )
{
levelstate.floornum = 17;
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
/*
* wolf_renderer.h: Wolfenstein3-D renderer.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from Quake II, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_renderer.c and wolf_opengl.c
*/
#ifndef __WOLF_RENDERER_H__
#define __WOLF_RENDERER_H__
extern void R_DrawBox( int x, int y, int w, int h, W32 color );
extern void R_Draw_Door( int x, int y, float z1, float z2, _boolean vertical, _boolean backside, int tex, int amount );
extern void R_Draw_Wall( float x, float y, float z1, float z2, int type, int tex );
extern void R_DrawSprites( void );
extern void R_DrawPsyched( W32 percent );
extern void R_DrawHUD( void );
extern void R_DrawNumber( int x, int y, int number );
extern void R_put_line( int x, int y, const char *string );
#endif /* __WOLF_RENDERER_H__ */

View File

@@ -0,0 +1,287 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_sprites.c: Wolfenstein3-D sprite handling.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* This code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
*/
#include "../wolfiphone.h"
/*
-----------------------------------------------------------------------------
Function: Sprite_Reset -Reset sprite status.
Parameters: Nothing.
Returns: Nothing.
Notes: Called only when client must reconnect will not set remove flag!
-----------------------------------------------------------------------------
*/
PUBLIC void Sprite_Reset( void )
{
levelData.numSprites = 0;
memset( levelData.sprites, 0, sizeof( levelData.sprites ) );
}
/*
-----------------------------------------------------------------------------
Function: Sprite_RemoveSprite -Remove sprite.
Parameters: sprite_id -[in] sprite id to remove.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Sprite_RemoveSprite( int sprite_id )
{
if( sprite_id == -1 )
{
return;
}
levelData.sprites[ sprite_id ].flags |= SPRT_REMOVE;
}
/*
-----------------------------------------------------------------------------
Function: Sprite_GetNewSprite -Get sprite index.
Parameters: Nothing.
Returns: "sprite id" index.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC int Sprite_GetNewSprite( void )
{
W32 n;
sprite_t* sprt;
for( n = 0, sprt = levelData.sprites ; n < levelData.numSprites ; ++n, ++sprt )
{
if( sprt->flags & SPRT_REMOVE )
{ // free spot: clear it first
memset( sprt, 0, sizeof( sprite_t ) );
return n;
}
}
if( levelData.numSprites >= MAX_SPRITES )
{
Com_Printf( "Warning n_of_sprt == MAX_SPRITES\n" );
return -1;
}
return levelData.numSprites++;
}
/*
-----------------------------------------------------------------------------
Function: Sprite_SetPos -Set sprite position.
Parameters: sprite_id -[in] sprite id to change.
x, y -[in] new x, y.
angle -[in] new angle to set.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Sprite_SetPos( int sprite_id, int x, int y, int angle )
{
if( sprite_id == -1 )
{
return;
}
levelData.sprites[ sprite_id ].x = x;
levelData.sprites[ sprite_id ].y = y;
levelData.sprites[ sprite_id ].ang = angle;
levelData.sprites[ sprite_id ].tilex = POS2TILE( x );
levelData.sprites[ sprite_id ].tiley = POS2TILE( y );
levelData.sprites[ sprite_id ].flags |= SPRT_CHG_POS;
if( ! (x & HALFTILE) ) // (x%TILEGLOBAL>=HALFTILE)
{
levelData.sprites[ sprite_id ].tilex--;
}
if( ! (y & HALFTILE) )
{
levelData.sprites[ sprite_id ].tiley--;
}
}
/*
-----------------------------------------------------------------------------
Function: Sprite_SetTex -Set sprite texture.
Parameters: sprite_id -[in] sprite id to change.
index -[in] texture index.
tex -[in] texture to set as.
Returns: Nothing.
Notes:
-----------------------------------------------------------------------------
*/
void CacheTextures( W16 start, W16 end );
PUBLIC void Sprite_SetTex( int sprite_id, int index, int tex )
{
if( sprite_id == -1 )
{
return;
}
CacheTextures( tex, tex );
if( index == -1 ) // one texture for each phase
{
levelData.sprites[ sprite_id ].tex[ 0 ] = tex;
levelData.sprites[ sprite_id ].flags |= SPRT_ONE_TEX;
}
else
{
levelData.sprites[ sprite_id ].tex[ index ] = tex;
}
levelData.sprites[ sprite_id ].flags |= SPRT_CHG_TEX;
}
#define MAXVISABLE 128
visobj_t vislist[ MAXVISABLE ];
/*
-----------------------------------------------------------------------------
Function: Sprite_CreateVisList -Compare function for vislist sorting.
Parameters: vis1, vis2 -[in] Two values to compare.
Returns:
<0 elem1 further than elem2
0 elem1 equal distance to elem2
>0 elem1 closer than elem2
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE int Sprite_cmpVis( const void *elem1, const void *elem2 )
{
// macro to get distance from a void pointer to visobj_t
#define vis_dist( vis ) ( ((visobj_t *)vis)->dist )
if( vis_dist( elem1 ) == vis_dist( elem2 ) )
{
return 0; // process equal distance
}
else
{
// if dist > sprite must be first
return vis_dist( elem1 ) < vis_dist( elem2 ) ? 1 : -1;
}
}
/*
-----------------------------------------------------------------------------
Function: Sprite_CreateVisList -Build and sort visibility list of sprites.
Parameters: Nothing.
Returns: Number of visible sprites.
Notes:
List is sorted from far to near.
List is based on tile visibility array, made by raycaster.
Called only by client.
-----------------------------------------------------------------------------
*/
PUBLIC int Sprite_CreateVisList( void )
{
W32 tx, ty, n, num_visible;
visobj_t *visptr;
sprite_t* sprt;
visptr = vislist;
num_visible = 0;
for( n = 0, sprt = levelData.sprites; n < levelData.numSprites; ++n, ++sprt )
{
if( sprt->flags & SPRT_REMOVE )
{
continue;
}
tx = sprt->tilex;
ty = sprt->tiley;
if( tx > 63 )
tx = 63;
if( ty > 63 )
ty = 63;
// can be in any of 4 surrounding tiles; not 9 - see definition of tilex & tiley
if( tile_visible[ tx ][ ty ] || tile_visible[ tx + 1 ][ ty ] ||
tile_visible[ tx ][ ty + 1 ] || tile_visible[ tx + 1 ][ ty + 1 ] )
{ // player spoted it
visptr->dist = LineLen2Point( sprt->x - Player.position.origin[ 0 ],
sprt->y-Player.position.origin[ 1 ],
Player.position.angle ); //FIXME viewport
visptr->x = sprt->x;
visptr->y = sprt->y;
visptr->ang = sprt->ang;
visptr->tex = sprt->tex[ 0 ]; //FIXME!
if( ++num_visible > MAXVISABLE )
{
break; // vislist full
}
visptr++;
}
}
// sorting list
if( num_visible ) // do not sort if no entries
{
qsort( vislist, num_visible, sizeof( visobj_t ), Sprite_cmpVis );
}
return num_visible;
}

View File

@@ -0,0 +1,429 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
/*
* wolf_sprites.h: Wolfenstein3-D sprite handling.
*
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
* Date: 2004
*
* Acknowledgement:
* Portion of this code was derived from NewWolf, and was originally
* written by DarkOne the Hacker.
*
* Portion of this code was derived from Wolfenstein3-D, and was originally
* written by Id Software, Inc.
*
*/
/*
Notes:
This module is implemented by wolf_sprites.c
*/
#ifndef __WOLF_SPRITES_H__
#define __WOLF_SPRITES_H__
//
// sprite constants
//
enum {
SPR_DEMO,
SPR_DEATHCAM,
//
// static sprites
//
SPR_STAT_0, SPR_STAT_1,SPR_STAT_2, SPR_STAT_3,
SPR_STAT_4, SPR_STAT_5,SPR_STAT_6, SPR_STAT_7,
SPR_STAT_8, SPR_STAT_9,SPR_STAT_10,SPR_STAT_11,
SPR_STAT_12,SPR_STAT_13,SPR_STAT_14,SPR_STAT_15,
SPR_STAT_16,SPR_STAT_17,SPR_STAT_18,SPR_STAT_19,
SPR_STAT_20,SPR_STAT_21,SPR_STAT_22,SPR_STAT_23,
SPR_STAT_24,SPR_STAT_25,SPR_STAT_26,SPR_STAT_27,
SPR_STAT_28,SPR_STAT_29,SPR_STAT_30,SPR_STAT_31,
SPR_STAT_32,SPR_STAT_33,SPR_STAT_34,SPR_STAT_35,
SPR_STAT_36,SPR_STAT_37,SPR_STAT_38,SPR_STAT_39,
SPR_STAT_40,SPR_STAT_41,SPR_STAT_42,SPR_STAT_43,
SPR_STAT_44,SPR_STAT_45,SPR_STAT_46,SPR_STAT_47,
SPR_STAT_48,SPR_STAT_49,SPR_STAT_50,SPR_STAT_51,
//
// Guard
//
SPR_GRD_S_1,SPR_GRD_S_2,SPR_GRD_S_3,SPR_GRD_S_4,
SPR_GRD_S_5,SPR_GRD_S_6,SPR_GRD_S_7,SPR_GRD_S_8,
SPR_GRD_W1_1,SPR_GRD_W1_2,SPR_GRD_W1_3,SPR_GRD_W1_4,
SPR_GRD_W1_5,SPR_GRD_W1_6,SPR_GRD_W1_7,SPR_GRD_W1_8,
SPR_GRD_W2_1,SPR_GRD_W2_2,SPR_GRD_W2_3,SPR_GRD_W2_4,
SPR_GRD_W2_5,SPR_GRD_W2_6,SPR_GRD_W2_7,SPR_GRD_W2_8,
SPR_GRD_W3_1,SPR_GRD_W3_2,SPR_GRD_W3_3,SPR_GRD_W3_4,
SPR_GRD_W3_5,SPR_GRD_W3_6,SPR_GRD_W3_7,SPR_GRD_W3_8,
SPR_GRD_W4_1,SPR_GRD_W4_2,SPR_GRD_W4_3,SPR_GRD_W4_4,
SPR_GRD_W4_5,SPR_GRD_W4_6,SPR_GRD_W4_7,SPR_GRD_W4_8,
SPR_GRD_PAIN_1,SPR_GRD_DIE_1,SPR_GRD_DIE_2,SPR_GRD_DIE_3,
SPR_GRD_PAIN_2,SPR_GRD_DEAD,
SPR_GRD_SHOOT1,SPR_GRD_SHOOT2,SPR_GRD_SHOOT3,
//
// Dog
//
SPR_DOG_W1_1,SPR_DOG_W1_2,SPR_DOG_W1_3,SPR_DOG_W1_4,
SPR_DOG_W1_5,SPR_DOG_W1_6,SPR_DOG_W1_7,SPR_DOG_W1_8,
SPR_DOG_W2_1,SPR_DOG_W2_2,SPR_DOG_W2_3,SPR_DOG_W2_4,
SPR_DOG_W2_5,SPR_DOG_W2_6,SPR_DOG_W2_7,SPR_DOG_W2_8,
SPR_DOG_W3_1,SPR_DOG_W3_2,SPR_DOG_W3_3,SPR_DOG_W3_4,
SPR_DOG_W3_5,SPR_DOG_W3_6,SPR_DOG_W3_7,SPR_DOG_W3_8,
SPR_DOG_W4_1,SPR_DOG_W4_2,SPR_DOG_W4_3,SPR_DOG_W4_4,
SPR_DOG_W4_5,SPR_DOG_W4_6,SPR_DOG_W4_7,SPR_DOG_W4_8,
SPR_DOG_DIE_1,SPR_DOG_DIE_2,SPR_DOG_DIE_3,SPR_DOG_DEAD,
SPR_DOG_JUMP1,SPR_DOG_JUMP2,SPR_DOG_JUMP3,
//
// SS
//
SPR_SS_S_1,SPR_SS_S_2,SPR_SS_S_3,SPR_SS_S_4,
SPR_SS_S_5,SPR_SS_S_6,SPR_SS_S_7,SPR_SS_S_8,
SPR_SS_W1_1,SPR_SS_W1_2,SPR_SS_W1_3,SPR_SS_W1_4,
SPR_SS_W1_5,SPR_SS_W1_6,SPR_SS_W1_7,SPR_SS_W1_8,
SPR_SS_W2_1,SPR_SS_W2_2,SPR_SS_W2_3,SPR_SS_W2_4,
SPR_SS_W2_5,SPR_SS_W2_6,SPR_SS_W2_7,SPR_SS_W2_8,
SPR_SS_W3_1,SPR_SS_W3_2,SPR_SS_W3_3,SPR_SS_W3_4,
SPR_SS_W3_5,SPR_SS_W3_6,SPR_SS_W3_7,SPR_SS_W3_8,
SPR_SS_W4_1,SPR_SS_W4_2,SPR_SS_W4_3,SPR_SS_W4_4,
SPR_SS_W4_5,SPR_SS_W4_6,SPR_SS_W4_7,SPR_SS_W4_8,
SPR_SS_PAIN_1,SPR_SS_DIE_1,SPR_SS_DIE_2,SPR_SS_DIE_3,
SPR_SS_PAIN_2,SPR_SS_DEAD,
SPR_SS_SHOOT1,SPR_SS_SHOOT2,SPR_SS_SHOOT3,
//
// Mutant
//
SPR_MUT_S_1,SPR_MUT_S_2,SPR_MUT_S_3,SPR_MUT_S_4,
SPR_MUT_S_5,SPR_MUT_S_6,SPR_MUT_S_7,SPR_MUT_S_8,
SPR_MUT_W1_1,SPR_MUT_W1_2,SPR_MUT_W1_3,SPR_MUT_W1_4,
SPR_MUT_W1_5,SPR_MUT_W1_6,SPR_MUT_W1_7,SPR_MUT_W1_8,
SPR_MUT_W2_1,SPR_MUT_W2_2,SPR_MUT_W2_3,SPR_MUT_W2_4,
SPR_MUT_W2_5,SPR_MUT_W2_6,SPR_MUT_W2_7,SPR_MUT_W2_8,
SPR_MUT_W3_1,SPR_MUT_W3_2,SPR_MUT_W3_3,SPR_MUT_W3_4,
SPR_MUT_W3_5,SPR_MUT_W3_6,SPR_MUT_W3_7,SPR_MUT_W3_8,
SPR_MUT_W4_1,SPR_MUT_W4_2,SPR_MUT_W4_3,SPR_MUT_W4_4,
SPR_MUT_W4_5,SPR_MUT_W4_6,SPR_MUT_W4_7,SPR_MUT_W4_8,
SPR_MUT_PAIN_1,SPR_MUT_DIE_1,SPR_MUT_DIE_2,SPR_MUT_DIE_3,
SPR_MUT_PAIN_2,SPR_MUT_DIE_4,SPR_MUT_DEAD,
SPR_MUT_SHOOT1,SPR_MUT_SHOOT2,SPR_MUT_SHOOT3,SPR_MUT_SHOOT4,
//
// Officer
//
SPR_OFC_S_1,SPR_OFC_S_2,SPR_OFC_S_3,SPR_OFC_S_4,
SPR_OFC_S_5,SPR_OFC_S_6,SPR_OFC_S_7,SPR_OFC_S_8,
SPR_OFC_W1_1,SPR_OFC_W1_2,SPR_OFC_W1_3,SPR_OFC_W1_4,
SPR_OFC_W1_5,SPR_OFC_W1_6,SPR_OFC_W1_7,SPR_OFC_W1_8,
SPR_OFC_W2_1,SPR_OFC_W2_2,SPR_OFC_W2_3,SPR_OFC_W2_4,
SPR_OFC_W2_5,SPR_OFC_W2_6,SPR_OFC_W2_7,SPR_OFC_W2_8,
SPR_OFC_W3_1,SPR_OFC_W3_2,SPR_OFC_W3_3,SPR_OFC_W3_4,
SPR_OFC_W3_5,SPR_OFC_W3_6,SPR_OFC_W3_7,SPR_OFC_W3_8,
SPR_OFC_W4_1,SPR_OFC_W4_2,SPR_OFC_W4_3,SPR_OFC_W4_4,
SPR_OFC_W4_5,SPR_OFC_W4_6,SPR_OFC_W4_7,SPR_OFC_W4_8,
SPR_OFC_PAIN_1,SPR_OFC_DIE_1,SPR_OFC_DIE_2,SPR_OFC_DIE_3,
SPR_OFC_PAIN_2,SPR_OFC_DIE_4,SPR_OFC_DEAD,
SPR_OFC_SHOOT1,SPR_OFC_SHOOT2,SPR_OFC_SHOOT3,
//
// Ghosts
//
SPR_BLINKY_W1,SPR_BLINKY_W2,SPR_PINKY_W1,SPR_PINKY_W2,
SPR_CLYDE_W1,SPR_CLYDE_W2,SPR_INKY_W1,SPR_INKY_W2,
//
// Hans
//
SPR_BOSS_W1,SPR_BOSS_W2,SPR_BOSS_W3,SPR_BOSS_W4,
SPR_BOSS_SHOOT1,SPR_BOSS_SHOOT2,SPR_BOSS_SHOOT3,SPR_BOSS_DEAD,
SPR_BOSS_DIE1,SPR_BOSS_DIE2,SPR_BOSS_DIE3,
//
// Schabbs
//
SPR_SCHABB_W1,SPR_SCHABB_W2,SPR_SCHABB_W3,SPR_SCHABB_W4,
SPR_SCHABB_SHOOT1,SPR_SCHABB_SHOOT2,
SPR_SCHABB_DIE1,SPR_SCHABB_DIE2,SPR_SCHABB_DIE3,SPR_SCHABB_DEAD,
SPR_HYPO1,SPR_HYPO2,SPR_HYPO3,SPR_HYPO4,
//
// Fake
//
SPR_FAKE_W1,SPR_FAKE_W2,SPR_FAKE_W3,SPR_FAKE_W4,
SPR_FAKE_SHOOT,SPR_FIRE1,SPR_FIRE2,
SPR_FAKE_DIE1,SPR_FAKE_DIE2,SPR_FAKE_DIE3,SPR_FAKE_DIE4,
SPR_FAKE_DIE5,SPR_FAKE_DEAD,
//
// Hitler
//
SPR_MECHA_W1,SPR_MECHA_W2,SPR_MECHA_W3,SPR_MECHA_W4,
SPR_MECHA_SHOOT1,SPR_MECHA_SHOOT2,SPR_MECHA_SHOOT3,SPR_MECHA_DEAD,
SPR_MECHA_DIE1,SPR_MECHA_DIE2,SPR_MECHA_DIE3,
SPR_HITLER_W1,SPR_HITLER_W2,SPR_HITLER_W3,SPR_HITLER_W4,
SPR_HITLER_SHOOT1,SPR_HITLER_SHOOT2,SPR_HITLER_SHOOT3,SPR_HITLER_DEAD,
SPR_HITLER_DIE1,SPR_HITLER_DIE2,SPR_HITLER_DIE3,SPR_HITLER_DIE4,
SPR_HITLER_DIE5,SPR_HITLER_DIE6,SPR_HITLER_DIE7,
//
// Giftmacher
//
SPR_GIFT_W1,SPR_GIFT_W2,SPR_GIFT_W3,SPR_GIFT_W4,
SPR_GIFT_SHOOT1,SPR_GIFT_SHOOT2,
SPR_GIFT_DIE1,SPR_GIFT_DIE2,SPR_GIFT_DIE3,SPR_GIFT_DEAD,
//
// Rocket, smoke and small explosion
//
SPR_ROCKET_1,SPR_ROCKET_2,SPR_ROCKET_3,SPR_ROCKET_4,
SPR_ROCKET_5,SPR_ROCKET_6,SPR_ROCKET_7,SPR_ROCKET_8,
SPR_SMOKE_1,SPR_SMOKE_2,SPR_SMOKE_3,SPR_SMOKE_4,
SPR_BOOM_1,SPR_BOOM_2,SPR_BOOM_3,
//
// Angel of Death's DeathSparks(tm)
//
SPR_HROCKET_1,SPR_HROCKET_2,SPR_HROCKET_3,SPR_HROCKET_4,
SPR_HROCKET_5,SPR_HROCKET_6,SPR_HROCKET_7,SPR_HROCKET_8,
SPR_HSMOKE_1,SPR_HSMOKE_2,SPR_HSMOKE_3,SPR_HSMOKE_4,
SPR_HBOOM_1,SPR_HBOOM_2,SPR_HBOOM_3,
SPR_SPARK1,SPR_SPARK2,SPR_SPARK3,SPR_SPARK4,
//
// Gretel
//
SPR_GRETEL_W1,SPR_GRETEL_W2,SPR_GRETEL_W3,SPR_GRETEL_W4,
SPR_GRETEL_SHOOT1,SPR_GRETEL_SHOOT2,SPR_GRETEL_SHOOT3,SPR_GRETEL_DEAD,
SPR_GRETEL_DIE1,SPR_GRETEL_DIE2,SPR_GRETEL_DIE3,
//
// Fat Face
//
SPR_FAT_W1,SPR_FAT_W2,SPR_FAT_W3,SPR_FAT_W4,
SPR_FAT_SHOOT1,SPR_FAT_SHOOT2,SPR_FAT_SHOOT3,SPR_FAT_SHOOT4,
SPR_FAT_DIE1,SPR_FAT_DIE2,SPR_FAT_DIE3,SPR_FAT_DEAD,
//
// bj
//
SPR_BJ_W1,SPR_BJ_W2,SPR_BJ_W3,SPR_BJ_W4,
SPR_BJ_JUMP1,SPR_BJ_JUMP2,SPR_BJ_JUMP3,SPR_BJ_JUMP4,
//
// SPEAR OF DESTINY
//
//
// Trans Grosse
//
SPR_TRANS_W1,SPR_TRANS_W2,SPR_TRANS_W3,SPR_TRANS_W4,
SPR_TRANS_SHOOT1,SPR_TRANS_SHOOT2,SPR_TRANS_SHOOT3,SPR_TRANS_DEAD,
SPR_TRANS_DIE1,SPR_TRANS_DIE2,SPR_TRANS_DIE3,
//
// Wilhelm
//
SPR_WILL_W1,SPR_WILL_W2,SPR_WILL_W3,SPR_WILL_W4,
SPR_WILL_SHOOT1,SPR_WILL_SHOOT2,SPR_WILL_SHOOT3,SPR_WILL_SHOOT4,
SPR_WILL_DIE1,SPR_WILL_DIE2,SPR_WILL_DIE3,SPR_WILL_DEAD,
//
// UberMutant
//
SPR_UBER_W1,SPR_UBER_W2,SPR_UBER_W3,SPR_UBER_W4,
SPR_UBER_SHOOT1,SPR_UBER_SHOOT2,SPR_UBER_SHOOT3,SPR_UBER_SHOOT4,
SPR_UBER_DIE1,SPR_UBER_DIE2,SPR_UBER_DIE3,SPR_UBER_DIE4,
SPR_UBER_DEAD,
//
// Death Knight
//
SPR_DEATH_W1,SPR_DEATH_W2,SPR_DEATH_W3,SPR_DEATH_W4,
SPR_DEATH_SHOOT1,SPR_DEATH_SHOOT2,SPR_DEATH_SHOOT3,SPR_DEATH_SHOOT4,
SPR_DEATH_DIE1,SPR_DEATH_DIE2,SPR_DEATH_DIE3,SPR_DEATH_DIE4,
SPR_DEATH_DIE5,SPR_DEATH_DIE6,SPR_DEATH_DEAD,
//
// Ghost
//
SPR_SPECTRE_W1,SPR_SPECTRE_W2,SPR_SPECTRE_W3,SPR_SPECTRE_W4,
SPR_SPECTRE_F1,SPR_SPECTRE_F2,SPR_SPECTRE_F3,SPR_SPECTRE_F4,
//
// Angel of Death
//
SPR_ANGEL_W1,SPR_ANGEL_W2,SPR_ANGEL_W3,SPR_ANGEL_W4,
SPR_ANGEL_SHOOT1,SPR_ANGEL_SHOOT2,SPR_ANGEL_TIRED1,SPR_ANGEL_TIRED2,
SPR_ANGEL_DIE1,SPR_ANGEL_DIE2,SPR_ANGEL_DIE3,SPR_ANGEL_DIE4,
SPR_ANGEL_DIE5,SPR_ANGEL_DIE6,SPR_ANGEL_DIE7,SPR_ANGEL_DEAD,
//
// player attack frames
//
SPR_KNIFEREADY,SPR_KNIFEATK1,SPR_KNIFEATK2,SPR_KNIFEATK3,
SPR_KNIFEATK4,
SPR_PISTOLREADY,SPR_PISTOLATK1,SPR_PISTOLATK2,SPR_PISTOLATK3,
SPR_PISTOLATK4,
SPR_MACHINEGUNREADY,SPR_MACHINEGUNATK1,SPR_MACHINEGUNATK2,MACHINEGUNATK3,
SPR_MACHINEGUNATK4,
SPR_CHAINREADY,SPR_CHAINATK1,SPR_CHAINATK2,SPR_CHAINATK3,
SPR_CHAINATK4,
};
#define SPRT_ONE_TEX 1
#define SPRT_NO_ROT 2
#define SPRT_CHG_POS 4
#define SPRT_CHG_TEX 8
#define SPRT_REMOVE 16
typedef struct sprite_s
{
vec3_t position;
int x, y, ang;
// very clever to make it not just (x>>TILESHIFT)
// but also (x>>TILESHIFT)-1 if (x%TILEWIDTH)<HALFTILE
// so we will check only 4 files instead of 9 as Carmack did!
int tilex, tiley;
// controls appearence of this sprite:
// SPRT_ONE_TEX: use one texture for each rotation
// SPRT_NO_ROT: do not rotate sprite (fence)
// SPRT_CHG_POS
// SPRT_CHG_TEX
// SPRT_REMOVE
int flags;
// 8 textures: one for each rotation phase!
// if SPRT_ONE_TEX flag use tex with index 0!
// these are Wolf sprite texture numbers, not OpenGL sprites
// or indexes in the textureManager list
int tex[ 8 ];
} sprite_t;
// total sprites on level in a moment
#define MAX_SPRITES 1024
typedef struct visobj_s
{
int viewx, viewheight; // obsolete, but will do in software rendering!
int dist; // how we will sort them
int x, y; // position in game space! (for OpenGL)
int ang; // for md2 rotation
int tex; // texture to draw (renderer must know what to draw by this number!
} visobj_t;
extern visobj_t vislist[];
extern void Sprite_Reset( void );
extern void Sprite_RemoveSprite( int sprite_id );
extern int Sprite_GetNewSprite( void );
extern void Sprite_SetPos( int sprite_id, int x, int y, int angle );
extern void Sprite_SetTex( int sprite_id, int index, int tex );
extern int Sprite_CreateVisList( void );
#endif /* __WOLF_SPRITES_H__ */

View File

@@ -0,0 +1,95 @@
/*
Copyright (C) 2004 Michael Liebscher
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.
*/
#include "../wolfiphone.h"
extern void Client_PrepRefresh( const char *r_mapname );
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PRIVATE void SV_GameMap_f( void )
{
char *map;
char r_mapname[ 32 ];
if( Cmd_Argc() != 2 )
{
Com_Printf( "USAGE: gamemap <map>\n" );
return;
}
// Com_DPrintf( "SV_GameMap( %s )\n", Cmd_Argv( 1 ) );
FS_CreatePath( va( "%s/save/current/", FS_Gamedir() ) );
// check for clearing the current savegame
map = Cmd_Argv( 1 );
// start up the next map
my_strlcpy( r_mapname, Cmd_Argv( 1 ), sizeof( r_mapname ) );
Client_PrepRefresh( r_mapname );
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void Map_f( void )
{
char *map;
char expanded[ MAX_GAMEPATH ];
// Check to make sure the level exists.
map = Cmd_Argv( 1 );
if( ! strstr( map, "." ) )
{
my_snprintf( expanded, sizeof( expanded ), "maps/%s.map", map );
}
else
{
my_snprintf( expanded, sizeof( expanded ), "maps/%s", map );
}
//sv.state = ss_dead; // don't save current level when changing
// SV_WipeSavegame( "current" );
SV_GameMap_f();
}

View File

@@ -0,0 +1,194 @@
/*
Copyright (C) 2004 Michael Liebscher
Copyright (C) 2000-2002 by DarkOne the Hacker
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.
*/
#include "../wolfiphone.h"
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void fire_hit( player_t *self )
{
entity_t *closest;
int dist, d1, n, shot_dist, damage;
Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "lsfx/023.wav" ), 1, ATTN_NORM, 0 );
// actually fire
dist = 0x7fffffff;
closest = NULL;
for( n = 0 ; n < NumGuards ; ++n )
{
if( Guards[ n ].flags & FL_SHOOTABLE ) // && Guards[n].flags&FL_VISABLE
{
shot_dist = Point2LineDist( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );
if( shot_dist > (2 * TILEGLOBAL / 3) )
{
continue; // miss
}
d1 = LineLen2Point( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );
if( d1 < 0 || d1 > dist )
{
continue;
}
if( ! Level_CheckLine( Guards[ n ].x, Guards[ n ].y, Player.position.origin[0], Player.position.origin[1], r_world ) )
{
//if( ! CheckLine( &Guards[ n ] ) )
continue; // obscured
}
dist = d1;
closest = &Guards[ n ];
}
}
if( ! closest || dist > TILE2POS( 1 ) )
{
return; // missed if further than 1.5 tiles
}
damage = US_RndT() >> 4;
A_DamageActor( closest, damage ); // hit something
}
/*
-----------------------------------------------------------------------------
Function:
Parameters:
Returns:
Notes:
-----------------------------------------------------------------------------
*/
PUBLIC void fire_lead( player_t *self )
{
entity_t *closest;
int damage;
int dx, dy, dist;
int d1, shot_dist, n;
switch( self->weapon )
{
case WEAPON_PISTOL:
Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/012.wav" ), 1, ATTN_NORM, 0 );
break;
case WEAPON_AUTO:
Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/011.wav" ), 1, ATTN_NORM, 0 );
break;
case WEAPON_CHAIN:
Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/013.wav" ), 1, ATTN_NORM, 0 );
break;
}
self->madenoise = true;
dist = 0x7fffffffl;
closest = NULL;
for( n = 0 ; n < NumGuards; ++n )
{
if( Guards[ n ].flags & FL_SHOOTABLE ) // && Guards[n].flags&FL_VISABLE
{
shot_dist = Point2LineDist( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );
if( shot_dist > (2 * TILEGLOBAL / 3) )
{
continue; // miss
}
d1 = LineLen2Point( Guards[ n ].x - self->position.origin[ 0 ], Guards[ n ].y - self->position.origin[ 1 ], self->position.angle );
if( d1 < 0 || d1 > dist )
{
continue;
}
if( ! Level_CheckLine( Guards[ n ].x, Guards[ n ].y, Player.position.origin[0], Player.position.origin[1], r_world ) )
{
//if( ! CheckLine( &Guards[ n ] ) )
continue; // obscured
}
dist = d1;
closest = &Guards[ n ];
}
}
if( ! closest ) // missed
{
r_trace_t trace;
trace.a = NormalizeAngle( self->position.angle - DEG2FINE( 2 ) + rand() % (DEG2FINE( 4 ) ) );
trace.x = self->position.origin[ 0 ];
trace.y = self->position.origin[ 1 ];
trace.flags = TRACE_BULLET;
trace.tile_vis = NULL;
R_Trace( &trace, r_world );
if( trace.flags & TRACE_HIT_DOOR )
{
Sound_StartSound( NULL, 0, CHAN_AUTO, Sound_RegisterSound( "lsfx/028.wav" ), 1, ATTN_NORM, 0 );
}
return;
}
// hit something
dx = ABS( closest->tilex - self->tilex );
dy = ABS( closest->tiley - self->tiley );
dist = max_of_2( dx, dy );
if( dist < 2 )
{
damage = US_RndT() / 4;
}
else if( dist < 4 )
{
damage = US_RndT() / 6;
}
else
{
if( US_RndT() / 12 < dist )
{
return; // missed
}
damage = US_RndT() / 6;
}
A_DamageActor( closest, damage );
}