CON: Add EVENT_DAMAGESPRITE, EVENT_POSTDAMAGESPRITE, EVENT_DAMAGEWALL, EVENT_DAMAGECEILING, and EVENT_DAMAGEFLOOR.

In these events, THISACTOR is the projectile (or source of damage), and RETURN is the sprite/wall/sector affected.
Set RETURN to -1 to cancel any hardcoded effects.
ud.return 1 through 5 are the parameters passed to hitradius if RADIUSEXPLOSION is the source of the damage. ud.return 1 is -1 otherwise.

New tokens "damageeventtile" and "damageeventtilerange" or tiledata[].gameflags & SFLAG_DAMAGEEVENT to enable processing for receivers with corresponding tilenums.

CON commands to replicate hardcoded effects (beyond switching tilenums, such as spawning glass) are forthcoming.

Use of EVENT_DAMAGEHPLANE is hereby discouraged.

Patch from Striker, based on work by Fox.

git-svn-id: https://svn.eduke32.com/eduke32@6771 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2018-03-17 03:26:10 +00:00
parent cab8c9aadf
commit 928ce686a6
9 changed files with 181 additions and 33 deletions

View file

@ -116,6 +116,12 @@ void A_RadiusDamage(int spriteNum, int blastRadius, int dmg1, int dmg2, int dmg3
int16_t *const sectorList = (int16_t *)tempbuf;
const int32_t maxSectors = sizeof(tempbuf)/sizeof(int16_t);
ud.returnvar[0] = blastRadius; // Allow checking for radius damage in EVENT_DAMAGE(SPRITE/WALL/FLOOR/CEILING) events.
ud.returnvar[1] = dmg1;
ud.returnvar[2] = dmg2;
ud.returnvar[3] = dmg3;
ud.returnvar[4] = dmg4;
if (pSprite->picnum == RPG && pSprite->xrepeat < 11)
goto SKIPWALLCHECK;
@ -139,9 +145,9 @@ void A_RadiusDamage(int spriteNum, int blastRadius, int dmg1, int dmg2, int dmg3
G_WallSpriteDist((uwalltype *)&wall[wall[w2].point2], pSprite) < blastRadius)
{
if (((sector[sectorNum].ceilingz-pSprite->z)>>8) < blastRadius)
Sect_DamageCeilingOrFloor(0, sectorNum);
Sect_DamageCeiling_Internal(spriteNum, sectorNum);
if (((pSprite->z-sector[sectorNum].floorz)>>8) < blastRadius)
Sect_DamageCeilingOrFloor(1, sectorNum);
Sect_DamageFloor_Internal(spriteNum, sectorNum);
}
uwalltype const *pWall;
@ -178,7 +184,7 @@ void A_RadiusDamage(int spriteNum, int blastRadius, int dmg1, int dmg2, int dmg3
pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum))
{
vec3_t const tmpvect = { pWall->x, pWall->y, pSprite->z };
A_DamageWall(spriteNum, w, &tmpvect, pSprite->picnum);
A_DamageWall_Internal(spriteNum, w, &tmpvect, pSprite->picnum);
}
}
}
@ -207,7 +213,7 @@ SKIPWALLCHECK:
{
if (A_CheckEnemySprite(pOther) && !cansee(pOther->x, pOther->y,pOther->z+q, pOther->sectnum, pSprite->x, pSprite->y, pSprite->z+q, pSprite->sectnum))
goto next_sprite;
A_DamageObject(otherSprite, spriteNum);
A_DamageObject_Internal(otherSprite, spriteNum);
}
}
else if (pOther->extra >= 0 && (uspritetype *)pOther != pSprite &&
@ -233,6 +239,12 @@ SKIPWALLCHECK:
if (d < blastRadius && cansee(pOther->x, pOther->y, pOther->z - ZOFFSET3, pOther->sectnum, pSprite->x,
pSprite->y, pSprite->z - ZOFFSET4, pSprite->sectnum))
{
if (A_CheckSpriteFlags(otherSprite, SFLAG_DAMAGEEVENT))
{
if (VM_OnEventWithReturn(EVENT_DAMAGESPRITE, spriteNum, -1, otherSprite) < 0)
goto next_sprite;
}
actor[otherSprite].ang = getangle(pOther->x-pSprite->x,pOther->y-pSprite->y);
if (pSprite->picnum == RPG && pOther->extra > 0)
@ -272,13 +284,16 @@ SKIPWALLCHECK:
pOther->xvel += (pSprite->extra<<2);
}
if (A_CheckSpriteFlags(otherSprite, SFLAG_DAMAGEEVENT))
VM_OnEventWithReturn(EVENT_POSTDAMAGESPRITE, spriteNum, -1, otherSprite);
if (pOther->picnum == PODFEM1 || pOther->picnum == FEM1 || pOther->picnum == FEM2 ||
pOther->picnum == FEM3 || pOther->picnum == FEM4 || pOther->picnum == FEM5 ||
pOther->picnum == FEM6 || pOther->picnum == FEM7 || pOther->picnum == FEM8 ||
pOther->picnum == FEM9 || pOther->picnum == FEM10 || pOther->picnum == STATUE ||
pOther->picnum == STATUEFLASH || pOther->picnum == SPACEMARINE || pOther->picnum == QUEBALL ||
pOther->picnum == STRIPEBALL)
A_DamageObject(otherSprite, spriteNum);
A_DamageObject_Internal(otherSprite, spriteNum);
}
else if (pSprite->extra == 0) actor[otherSprite].extra = 0;
@ -2697,14 +2712,16 @@ static void Proj_BounceOffWall(spritetype *s, int j)
// Maybe damage a ceiling or floor as the consequence of projectile impact.
// Returns 1 if sprite <s> should be killed.
// NOTE: Compare with Proj_MaybeDamageCF2() in sector.c
static int Proj_MaybeDamageCF(uspritetype const * const s)
static int Proj_MaybeDamageCF(int spriteNum)
{
uspritetype const * const s = &sprite[spriteNum];
if (s->zvel < 0)
{
if ((sector[s->sectnum].ceilingstat&1) && sector[s->sectnum].ceilingpal == 0)
return 1;
Sect_DamageCeilingOrFloor(0, s->sectnum);
Sect_DamageCeiling(spriteNum, s->sectnum);
}
else if (s->zvel > 0)
{
@ -2715,7 +2732,7 @@ static int Proj_MaybeDamageCF(uspritetype const * const s)
return 0;
}
Sect_DamageCeilingOrFloor(1, s->sectnum);
Sect_DamageFloor(spriteNum, s->sectnum);
}
return 0;
@ -2954,7 +2971,7 @@ ACTOR_STATIC void Proj_MoveCustom(int const spriteNum)
case 16384:
setsprite(spriteNum, &davect);
if (Proj_MaybeDamageCF((uspritetype *)pSprite))
if (Proj_MaybeDamageCF(spriteNum))
{
A_DeleteSprite(spriteNum);
return;
@ -3172,7 +3189,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
case 16384:
setsprite(spriteNum, &davect);
if (Proj_MaybeDamageCF((uspritetype *)pSprite))
if (Proj_MaybeDamageCF(spriteNum))
DELETE_SPRITE_AND_CONTINUE(spriteNum);
if (pSprite->picnum == FREEZEBLAST)

View file

@ -254,7 +254,8 @@ enum sflags_t
SFLAG_HURTSPAWNBLOOD = 0x00400000,
SFLAG_GREENSLIMEFOOD = 0x00800000,
SFLAG_REALCLIPDIST = 0x01000000,
SFLAG_WAKEUPBADGUYS = 0x02000000
SFLAG_WAKEUPBADGUYS = 0x02000000,
SFLAG_DAMAGEEVENT = 0x04000000,
};
// Custom projectiles "workslike" flags.

View file

@ -150,6 +150,11 @@ enum GameEvent_t {
EVENT_CONTINUELEVELMUSICSLOT,
EVENT_DISPLAYPOINTER,
EVENT_LASTWEAPON,
EVENT_DAMAGESPRITE,
EVENT_POSTDAMAGESPRITE,
EVENT_DAMAGEWALL,
EVENT_DAMAGEFLOOR,
EVENT_DAMAGECEILING,
#ifdef LUNATIC
EVENT_ANIMATEALLSPRITES,
#endif

View file

@ -153,7 +153,7 @@ extern camera_t g_camera;
#define MAXPWLOCKOUT 128
#define MAXRTSNAME 128
#define MAX_RETURN_VALUES 4
#define MAX_RETURN_VALUES 6
// KEEPINSYNC lunatic/_defs_game.lua
typedef struct {

View file

@ -149,6 +149,8 @@ static tokenmap_t const vm_keywords[] =
{ "count", CON_COUNT },
{ "cstat", CON_CSTAT },
{ "cstator", CON_CSTATOR },
{ "damageeventtile", CON_DAMAGEEVENTTILE },
{ "damageeventtilerange", CON_DAMAGEEVENTTILERANGE },
{ "debris", CON_DEBRIS },
{ "debug", CON_DEBUG },
{ "default", CON_DEFAULT },
@ -759,6 +761,11 @@ const char *EventNames[MAXEVENTS] =
"EVENT_CONTINUELEVELMUSICSLOT",
"EVENT_DISPLAYPOINTER",
"EVENT_LASTWEAPON",
"EVENT_DAMAGESPRITE",
"EVENT_POSTDAMAGESPRITE",
"EVENT_DAMAGEWALL",
"EVENT_DAMAGEFLOOR",
"EVENT_DAMAGECEILING",
#ifdef LUNATIC
"EVENT_ANIMATEALLSPRITES",
#endif
@ -4585,6 +4592,59 @@ DO_DEFSTATE:
continue;
}
case CON_DAMAGEEVENTTILE:
{
if (EDUKE32_PREDICT_FALSE(g_processingState || g_parsingActorPtr))
{
C_ReportError(ERROR_FOUNDWITHIN);
g_errorCnt++;
}
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE);
j = *(g_scriptPtr - 1);
if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXTILES))
{
C_ReportError(ERROR_EXCEEDSMAXTILES);
g_errorCnt++;
continue;
}
g_tile[j].flags |= SFLAG_DAMAGEEVENT;
continue;
}
case CON_DAMAGEEVENTTILERANGE:
{
if (EDUKE32_PREDICT_FALSE(g_processingState || g_parsingActorPtr))
{
C_ReportError(ERROR_FOUNDWITHIN);
g_errorCnt++;
}
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE);
i = *(g_scriptPtr - 1);
C_GetNextValue(LABEL_DEFINE);
j = *(g_scriptPtr - 1);
if (EDUKE32_PREDICT_FALSE((unsigned)i >= MAXTILES || (unsigned)j >= MAXTILES))
{
C_ReportError(ERROR_EXCEEDSMAXTILES);
g_errorCnt++;
continue;
}
for (tiledata_t * t = g_tile + i, * t_end = g_tile + j; t <= t_end; ++t)
t->flags |= SFLAG_DAMAGEEVENT;
continue;
}
case CON_SPRITEFLAGS:
if (!g_parsingActorPtr && g_processingState == 0)
{
@ -6352,6 +6412,7 @@ static void C_AddDefaultDefinitions(void)
{ "SFLAG_GREENSLIMEFOOD", SFLAG_GREENSLIMEFOOD },
{ "SFLAG_REALCLIPDIST", SFLAG_REALCLIPDIST },
{ "SFLAG_WAKEUPBADGUYS", SFLAG_WAKEUPBADGUYS },
{ "SFLAG_DAMAGEEVENT", SFLAG_DAMAGEEVENT },
{ "STR_MAPNAME", STR_MAPNAME },
{ "STR_MAPFILENAME", STR_MAPFILENAME },

View file

@ -1247,6 +1247,8 @@ enum ScriptKeywords_t
CON_SHOWVIEWQ16UNBIASED,// 426
CON_GETTILEDATA, // 427
CON_SETTILEDATA, // 428
CON_DAMAGEEVENTTILE, // 429
CON_DAMAGEEVENTTILERANGE, // 430
CON_END
};
// KEEPINSYNC with the keyword list in lunatic/con_lang.lua

View file

@ -581,7 +581,7 @@ static inline void HandleHitWall(hitdata_t *hitData)
// Maybe damage a ceiling or floor as the consequence of projectile impact.
// Returns 1 if projectile hit a parallaxed ceiling.
// NOTE: Compare with Proj_MaybeDamageCF() in actors.c
static int Proj_MaybeDamageCF2(int const zvel, int const hitSect)
static int Proj_MaybeDamageCF2(int const spriteNum, int const zvel, int const hitSect)
{
Bassert(hitSect >= 0);
@ -590,7 +590,7 @@ static int Proj_MaybeDamageCF2(int const zvel, int const hitSect)
if (sector[hitSect].ceilingstat&1)
return 1;
Sect_DamageCeilingOrFloor(0, hitSect);
Sect_DamageCeiling(spriteNum, hitSect);
}
else if (zvel > 0)
{
@ -601,7 +601,7 @@ static int Proj_MaybeDamageCF2(int const zvel, int const hitSect)
return 0;
}
Sect_DamageCeilingOrFloor(1, hitSect);
Sect_DamageFloor(spriteNum, hitSect);
}
return 0;
@ -622,7 +622,7 @@ static int P_PostFireHitscan(int const playerNum, int const spriteNum, hitdata_t
{
if (hitData->wall == -1 && hitData->sprite == -1)
{
if (Proj_MaybeDamageCF2(zvel, hitData->sect))
if (Proj_MaybeDamageCF2(spriteNum, zvel, hitData->sect))
{
sprite[spriteNum].xrepeat = 0;
sprite[spriteNum].yrepeat = 0;
@ -746,7 +746,7 @@ static int A_PostFireHitscan(const hitdata_t *hitData, int const spriteNum, int
}
else
{
if (Proj_MaybeDamageCF2(zvel, hitData->sect))
if (Proj_MaybeDamageCF2(returnSprite, zvel, hitData->sect))
{
sprite[returnSprite].xrepeat = 0;
sprite[returnSprite].yrepeat = 0;
@ -1206,7 +1206,7 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
if (hitData.wall == -1 && hitData.sprite == -1 && hitData.sect >= 0)
{
Proj_MaybeDamageCF2(Zvel, hitData.sect);
Proj_MaybeDamageCF2(otherSprite, Zvel, hitData.sect);
}
else if (hitData.sprite >= 0)
A_DamageObject(hitData.sprite, otherSprite);

View file

@ -1479,11 +1479,17 @@ static void G_BreakWall(int tileNum, int spriteNum, int wallNum)
A_SpawnWallGlass(spriteNum,wallNum,10);
}
void A_DamageWall(int spriteNum, int wallNum, const vec3_t *vPos, int weaponNum)
void A_DamageWall_Internal(int spriteNum, int wallNum, const vec3_t *vPos, int weaponNum)
{
int16_t sectNum = -1;
walltype *pWall = &wall[wallNum];
if ((g_tile[pWall->overpicnum].flags & SFLAG_DAMAGEEVENT) || (g_tile[pWall->picnum].flags & SFLAG_DAMAGEEVENT))
{
if (VM_OnEventWithReturn(EVENT_DAMAGEWALL, spriteNum, -1, wallNum) < 0)
return;
}
if (pWall->overpicnum == MIRROR && pWall->pal != 4 &&
A_CheckSpriteFlags(spriteNum, SFLAG_PROJECTILE) &&
(SpriteProjectile[spriteNum].workslike & PROJECTILE_RPG))
@ -1753,19 +1759,53 @@ void A_DamageWall(int spriteNum, int wallNum, const vec3_t *vPos, int weaponNum)
}
}
// NOTE: return value never examined in any of the callers.
int Sect_DamageCeilingOrFloor(int const dmgFloor, int const sectNum)
void A_DamageWall(int spriteNum, int wallNum, const vec3_t *vPos, int weaponNum)
{
ud.returnvar[0] = -1;
A_DamageWall_Internal(spriteNum, wallNum, vPos, weaponNum);
}
void Sect_DamageFloor_Internal(int const spriteNum, int const sectNum)
{
int16_t tileNum = sector[sectNum].floorpicnum;
if (g_tile[tileNum].flags & SFLAG_DAMAGEEVENT)
{
if (VM_OnEventWithReturn(EVENT_DAMAGEFLOOR, spriteNum, -1, sectNum) < 0)
return;
}
// NOTE: pass RETURN in the dist argument, too.
int const RETURN_in = dmgFloor ? 131072 + sectNum : 65536 + sectNum;
int32_t const returnValue =
VM_OnEventWithBoth(EVENT_DAMAGEHPLANE, g_player[screenpeek].ps->i, screenpeek, RETURN_in, RETURN_in);
int const RETURN_in = 131072 + sectNum;
/* int32_t const returnValue = */ VM_OnEventWithBoth(EVENT_DAMAGEHPLANE, -1, -1, RETURN_in, RETURN_in);
#if 0
// No hard-coded floor damage effects.
if (returnValue < 0)
return;
#endif
}
void Sect_DamageFloor(int const spriteNum, int const sectNum)
{
ud.returnvar[0] = -1;
Sect_DamageFloor_Internal(spriteNum, sectNum);
}
void Sect_DamageCeiling_Internal(int const spriteNum, int const sectNum)
{
int16_t tileNum = sector[sectNum].ceilingpicnum;
if (g_tile[tileNum].flags & SFLAG_DAMAGEEVENT)
{
if (VM_OnEventWithReturn(EVENT_DAMAGECEILING, spriteNum, -1, sectNum) < 0)
return;
}
// NOTE: pass RETURN in the dist argument, too.
int const RETURN_in = 65536 + sectNum;
int32_t const returnValue = VM_OnEventWithBoth(EVENT_DAMAGEHPLANE, -1, -1, RETURN_in, RETURN_in);
if (returnValue < 0)
return 0;
if (dmgFloor)
return 0;
return;
int16_t * const pPicnum = &sector[sectNum].ceilingpicnum;
@ -1813,19 +1853,27 @@ int Sect_DamageCeilingOrFloor(int const dmgFloor, int const sectNum)
T5(i) = 1;
}
}
return 1;
}
}
return 0;
void Sect_DamageCeiling(int const spriteNum, int const sectNum)
{
ud.returnvar[0] = -1;
Sect_DamageCeiling_Internal(spriteNum, sectNum);
}
// hard coded props... :(
void A_DamageObject(int spriteNum, int const dmgSrc)
void A_DamageObject_Internal(int spriteNum, int const dmgSrc)
{
if (g_netClient)
return;
if (A_CheckSpriteFlags(spriteNum, SFLAG_DAMAGEEVENT))
{
if (VM_OnEventWithReturn(EVENT_DAMAGESPRITE, dmgSrc, -1, spriteNum) < 0)
return;
}
int radiusDamage = 0;
spriteNum &= (MAXSPRITES-1);
@ -2272,6 +2320,9 @@ void A_DamageObject(int spriteNum, int const dmgSrc)
actor[spriteNum].extra += sprite[dmgSrc].extra;
actor[spriteNum].ang = sprite[dmgSrc].ang;
actor[spriteNum].owner = sprite[dmgSrc].owner;
if(A_CheckSpriteFlags(spriteNum, SFLAG_DAMAGEEVENT))
VM_OnEventWithReturn(EVENT_POSTDAMAGESPRITE, dmgSrc, -1, spriteNum);
}
if (sprite[spriteNum].statnum == STAT_PLAYER)
@ -2294,6 +2345,12 @@ void A_DamageObject(int spriteNum, int const dmgSrc)
}
}
void A_DamageObject(int spriteNum, int const dmgSrc)
{
ud.returnvar[0] = -1;
A_DamageObject_Internal(spriteNum, dmgSrc);
}
void G_AlignWarpElevators(void)
{
for (bssize_t SPRITES_OF(STAT_EFFECTOR, i))

View file

@ -118,7 +118,9 @@ void G_ActivateBySector(int sect,int j);
int S_FindMusicSFX(int sectNum, int *sndptr);
int A_CallSound(int sectNum,int spriteNum);
int A_CheckHitSprite(int spriteNum,int16_t *hitSprite);
void A_DamageObject_Internal(int spriteNum, int const dmgSrc);
void A_DamageObject(int spriteNum,int const dmgSrc);
void A_DamageWall_Internal(int spr, int dawallnum, const vec3_t *pos, int atwith);
void A_DamageWall(int spr,int dawallnum,const vec3_t *pos,int atwith);
int __fastcall A_FindPlayer(const spritetype *pSprite,int32_t *dist);
void G_AlignWarpElevators(void);
@ -139,7 +141,10 @@ int isanearoperator(int lotag);
int isanunderoperator(int lotag);
int P_ActivateSwitch(int playerNum, int nObject, int nSwitchType);
void P_CheckSectors(int snum);
int Sect_DamageCeilingOrFloor(int const dmgFloor, int const sectNum);
void Sect_DamageFloor_Internal(int const spriteNum, int const sectNum);
void Sect_DamageFloor(int const spriteNum, int const sectNum);
void Sect_DamageCeiling_Internal(int const spriteNum, int const sectNum);
void Sect_DamageCeiling(int const spriteNum, int const sectNum);
int SetAnimation(int sectNum,int32_t *animPtr,int goalVal,int animVel);
#define FORCEFIELD_CSTAT (64+16+4+1)