From 928ce686a69b81984a3eea1fe2570a1e36773ba8 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Sat, 17 Mar 2018 03:26:10 +0000 Subject: [PATCH] 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 --- source/duke3d/src/actors.cpp | 37 ++++++++++---- source/duke3d/src/actors.h | 3 +- source/duke3d/src/events_defs.h | 5 ++ source/duke3d/src/game.h | 2 +- source/duke3d/src/gamedef.cpp | 61 +++++++++++++++++++++++ source/duke3d/src/gamedef.h | 2 + source/duke3d/src/player.cpp | 12 ++--- source/duke3d/src/sector.cpp | 85 +++++++++++++++++++++++++++------ source/duke3d/src/sector.h | 7 ++- 9 files changed, 181 insertions(+), 33 deletions(-) diff --git a/source/duke3d/src/actors.cpp b/source/duke3d/src/actors.cpp index 33bccf1f0..c996063c9 100644 --- a/source/duke3d/src/actors.cpp +++ b/source/duke3d/src/actors.cpp @@ -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 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) diff --git a/source/duke3d/src/actors.h b/source/duke3d/src/actors.h index a77ccf3c5..05980ac58 100644 --- a/source/duke3d/src/actors.h +++ b/source/duke3d/src/actors.h @@ -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. diff --git a/source/duke3d/src/events_defs.h b/source/duke3d/src/events_defs.h index c567ecb3d..5fc039b2b 100644 --- a/source/duke3d/src/events_defs.h +++ b/source/duke3d/src/events_defs.h @@ -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 diff --git a/source/duke3d/src/game.h b/source/duke3d/src/game.h index d34c15413..d40a268c1 100644 --- a/source/duke3d/src/game.h +++ b/source/duke3d/src/game.h @@ -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 { diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index 4df2a1229..b11ae38f9 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -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 }, diff --git a/source/duke3d/src/gamedef.h b/source/duke3d/src/gamedef.h index 900e94b08..1110ef6bb 100644 --- a/source/duke3d/src/gamedef.h +++ b/source/duke3d/src/gamedef.h @@ -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 diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index 4fe9a3ad8..5e9a99b19 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -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); diff --git a/source/duke3d/src/sector.cpp b/source/duke3d/src/sector.cpp index 8a2436279..7b680d5f3 100644 --- a/source/duke3d/src/sector.cpp +++ b/source/duke3d/src/sector.cpp @@ -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 = §or[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)) diff --git a/source/duke3d/src/sector.h b/source/duke3d/src/sector.h index 3349ff884..cd1b99b4d 100644 --- a/source/duke3d/src/sector.h +++ b/source/duke3d/src/sector.h @@ -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)