diff --git a/polymer/eduke32/source/actors.h b/polymer/eduke32/source/actors.h index 1a2f996a1..f617317be 100644 --- a/polymer/eduke32/source/actors.h +++ b/polymer/eduke32/source/actors.h @@ -123,6 +123,8 @@ typedef struct { int16_t picnum,ang,extra,owner; //8b int16_t movflag,tempang,timetosleep; //6b + // NOTE: shootzvel is not exposed but only used temporarily in player.c + // shooting routines. int16_t actorstayput, dispicnum, shootzvel, cgg; // 8b int16_t lightId, lightcount, lightmaxrange; //6b diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index cdc22b043..69ae5e975 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -2321,31 +2321,24 @@ nullquote: case CON_EZSHOOT: case CON_ZSHOOT: insptr++; - { int32_t j; - - if (tw != CON_ESHOOT) - { - actor[vm.g_i].shootzvel = Gv_GetVarX(*insptr++); - if (actor[vm.g_i].shootzvel == 0) - actor[vm.g_i].shootzvel = 1; - } + // NOTE: (int16_t) cast because actor[].shootzvel is int16_t + // and we want exclude that SHOOT_HARDCODED_ZVEL is passed. + const int32_t zvel = (tw == CON_ESHOOT) ? + SHOOT_HARDCODED_ZVEL : (int16_t)Gv_GetVarX(*insptr++); if ((unsigned)vm.g_sp->sectnum >= (unsigned)numsectors) { CON_ERRPRINTF("Invalid sector %d\n", TrackerCast(vm.g_sp->sectnum)); insptr++; - actor[vm.g_i].shootzvel=0; continue; } - j = A_Shoot(vm.g_i,*insptr++); + j = A_ShootWithZvel(vm.g_i,*insptr++,zvel); if (tw != CON_ZSHOOT) aGameVars[g_iReturnVarID].val.lValue = j; - - actor[vm.g_i].shootzvel=0; } continue; @@ -2358,40 +2351,31 @@ nullquote: if ((unsigned)vm.g_sp->sectnum >= (unsigned)numsectors) { CON_ERRPRINTF("Invalid sector %d\n", TrackerCast(vm.g_sp->sectnum)); - actor[vm.g_i].shootzvel=0; continue; } j = A_Shoot(vm.g_i, j); if (tw == CON_ESHOOTVAR) aGameVars[g_iReturnVarID].val.lValue = j; - actor[vm.g_i].shootzvel=0; continue; } case CON_EZSHOOTVAR: case CON_ZSHOOTVAR: insptr++; - - actor[vm.g_i].shootzvel = Gv_GetVarX(*insptr++); - - if (actor[vm.g_i].shootzvel == 0) - actor[vm.g_i].shootzvel = 1; - { + const int32_t zvel = (int16_t)Gv_GetVarX(*insptr++); int32_t j=Gv_GetVarX(*insptr++); if ((unsigned)vm.g_sp->sectnum >= (unsigned)numsectors) { CON_ERRPRINTF("Invalid sector %d\n", TrackerCast(vm.g_sp->sectnum)); - actor[vm.g_i].shootzvel=0; continue; } - j = A_Shoot(vm.g_i, j); + j = A_ShootWithZvel(vm.g_i, j, zvel); if (tw == CON_EZSHOOTVAR) aGameVars[g_iReturnVarID].val.lValue = j; - actor[vm.g_i].shootzvel=0; continue; } diff --git a/polymer/eduke32/source/lunatic/con_lang.lua b/polymer/eduke32/source/lunatic/con_lang.lua index 9f59d383b..3942d6ee4 100644 --- a/polymer/eduke32/source/lunatic/con_lang.lua +++ b/polymer/eduke32/source/lunatic/con_lang.lua @@ -64,6 +64,7 @@ PROJ = { } -- PROJ_* define -> projectile_t member name +--[[ PROJ_MEMBNAME = { [PROJ.PROJ_WORKSLIKE] = "workslike", [PROJ.PROJ_SPAWNS] = "spawns", @@ -95,6 +96,7 @@ PROJ_MEMBNAME = { [PROJ.PROJ_RANGE] = "range", [PROJ.PROJ_FLASH_COLOR] = "flashcolor", -- NAME } +--]] -- TODO: EVENT_INIT currently can't run since we init Lunatic state only afterwards EVENT = { @@ -387,6 +389,7 @@ local ActorLabels = { httempang = AC".tempang", htactorstayput = AC".actorstayput", htdispicnum = { AC".dispicnum" }, + -- NOTE: no access for .shootzvel httimetosleep = AC".timetosleep", htfloorz = AC".floorz", htceilingz = AC".ceilingz", @@ -734,35 +737,35 @@ StructAccessCode = local PROJ = function(memb) return "projectile[%s]"..memb end local ProjectileLabels = { - workslike = PROJ"workslike", - cstat = PROJ"cstat", - hitradius = PROJ"hitradius", - range = PROJ"range", - flashcolor = PROJ"flashcolor", - spawns = { PROJ"spawns" }, - sound = PROJ"sound", - isound = PROJ"isound", - vel = PROJ"vel", - decal = { PROJ"decal" }, - trail = { PROJ"trail" }, - tnum = PROJ"tnum", - drop = PROJ"drop", - offset = PROJ"offset", - bounces = PROJ"bounces", - bsound = PROJ"bsound", - toffset = PROJ"toffset", - extra = PROJ"extra", - extra_rand = PROJ"extra_rand", - sxrepeat = PROJ"sxrepeat", - syrepeat = PROJ"syrepeat", - txrepeat = PROJ"txrepeat", - tyrepeat = PROJ"tyrepeat", - shade = PROJ"shade", - xrepeat = PROJ"xrepeat", - yrepeat = PROJ"yrepeat", - pal = PROJ"pal", - velmult = PROJ"movecnt", -- NAME - clipdist = PROJ"clipdist", + workslike = PROJ".workslike", + cstat = PROJ".cstat", + hitradius = PROJ".hitradius", + range = PROJ".range", + flashcolor = PROJ".flashcolor", + spawns = { PROJ".spawns" }, + sound = PROJ".sound", + isound = PROJ".isound", + vel = PROJ".vel", + decal = { PROJ".decal" }, + trail = { PROJ".trail" }, + tnum = PROJ".tnum", + drop = PROJ".drop", + offset = PROJ".offset", + bounces = PROJ".bounces", + bsound = PROJ".bsound", + toffset = PROJ".toffset", + extra = PROJ".extra", + extra_rand = PROJ".extra_rand", + sxrepeat = PROJ".sxrepeat", + syrepeat = PROJ".syrepeat", + txrepeat = PROJ".txrepeat", + tyrepeat = PROJ".tyrepeat", + shade = PROJ".shade", + xrepeat = PROJ".xrepeat", + yrepeat = PROJ".yrepeat", + pal = PROJ".pal", + velmult = PROJ".movecnt", -- NAME + clipdist = PROJ".clipdist", } -- These structs cannot be accessed by inline array exprs in CON: diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua index 59a49b383..64f1c0a70 100644 --- a/polymer/eduke32/source/lunatic/control.lua +++ b/polymer/eduke32/source/lunatic/control.lua @@ -434,7 +434,7 @@ end function _A_Shoot(i, atwith) check_sprite_idx(i) check_tile_idx(atwith) - return ffiC.A_Shoot(i, atwith) + return ffiC.A_ShootWithZvel(i, atwith, 0x80000000) -- SHOOT_HARDCODED_ZVEL end function _A_IncurDamage(sn) diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua index fcb3d922f..a87c787d1 100644 --- a/polymer/eduke32/source/lunatic/defs.ilua +++ b/polymer/eduke32/source/lunatic/defs.ilua @@ -502,7 +502,7 @@ const int32_t g_currentMenu; int32_t A_IncurDamage(int32_t sn); // not bound-checked! void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap); -int32_t A_Shoot(int32_t i, int32_t atwith); +int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel); int32_t A_IncurDamage(int32_t sn); int32_t A_Spawn(int32_t j, int32_t pn); void VM_FallSprite(int32_t i); diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua index 0bc1d1090..8d81e252d 100644 --- a/polymer/eduke32/source/lunatic/test.elua +++ b/polymer/eduke32/source/lunatic/test.elua @@ -263,7 +263,7 @@ gameevent(gv.EVENT_ENTERLEVEL, -- MORTER2 from test/weaponvars.con player[0].weapon.SHOTGUN.shoots = 1653 - projectile[1653].drop = -200 + projectile[1653].drop = 0 checkfail("gameevent('GAME', function() print('qwe') end)", "must be called from top level") diff --git a/polymer/eduke32/source/lunatic/test/weaponvars.con b/polymer/eduke32/source/lunatic/test/weaponvars.con index 63a163390..ce907f5c9 100644 --- a/polymer/eduke32/source/lunatic/test/weaponvars.con +++ b/polymer/eduke32/source/lunatic/test/weaponvars.con @@ -1,4 +1,6 @@ gamevar snd 351 0 // thunder sound +gamevar tmp 0 0 +gamevar tmp2 0 0 gamevar shoots 2605 2 // RPG gamevar WEAPON1_SHOOTS 2605 0 @@ -6,11 +8,11 @@ gamevar WEAPON1_SHOOTS 2605 0 define MORTER2 1653 defineprojectile MORTER2 PROJ_WORKSLIKE 6150 defineprojectile MORTER2 PROJ_SPAWNS EXPLOSION2 -defineprojectile MORTER2 PROJ_SOUND MORTER2_SHOOT +defineprojectile MORTER2 PROJ_SOUND RPG_SHOOT defineprojectile MORTER2 PROJ_VEL 600 defineprojectile MORTER2 PROJ_EXTRA 165 defineprojectile MORTER2 PROJ_EXTRA_RAND 10 -defineprojectile MORTER2 PROJ_DROP 0 // tested in test.elua +defineprojectile MORTER2 PROJ_DROP -200 // tested in test.elua defineprojectile MORTER2 PROJ_ISOUND PIPEBOMB_EXPLODE defineprojectile MORTER2 PROJ_HITRADIUS 2800 defineprojectile MORTER2 PROJ_BOUNCES 4 @@ -23,3 +25,15 @@ onevent EVENT_GAME setvarvar WEAPON1_FIRESOUND snd // setvarvar WEAPON1_SHOOTS shoots endevent + +useractor notenemy 909 // tree trunk + ifcount 120 + { + ezshoot -4096 MORTER2 + getthisprojectile[RETURN].vel tmp + randvar tmp2 500 + subvarvar tmp tmp2 + setthisprojectile[RETURN].vel tmp + resetcount + } +enda diff --git a/polymer/eduke32/source/player.c b/polymer/eduke32/source/player.c index 45be14ca7..bf9006aa2 100644 --- a/polymer/eduke32/source/player.c +++ b/polymer/eduke32/source/player.c @@ -440,6 +440,14 @@ static void Proj_MaybeAddSpread(int32_t not_accurate_p, int32_t *zvel, int16_t * } } + +static int32_t use_actor_shootzvel = 0; + +static int32_t A_GetShootZvel(int32_t i, int32_t defaultzvel) +{ + return use_actor_shootzvel ? actor[i].shootzvel : defaultzvel; +} + // Prepare hitscan weapon fired from player p. static void P_PreFireHitscan(int32_t i, int32_t p, int32_t atwith, vec3_t *srcvect, int32_t *zvel, int16_t *sa, @@ -477,9 +485,7 @@ static void P_PreFireHitscan(int32_t i, int32_t p, int32_t atwith, { hitdata_t hit; - *zvel = (100-ps->horiz-ps->horizoff)<<5; - if (actor[i].shootzvel) - *zvel = actor[i].shootzvel; + *zvel = A_GetShootZvel(i, (100-ps->horiz-ps->horizoff)<<5); hitscan(srcvect, sprite[i].sectnum, sintable[(*sa+512)&2047], sintable[*sa&2047], *zvel<<6,&hit,CLIPMASK1); @@ -544,8 +550,7 @@ static int32_t Proj_DoHitscan(int32_t i, int32_t cstatmask, s->cstat &= ~cstatmask; - if (actor[i].shootzvel) - zvel = actor[i].shootzvel; + zvel = A_GetShootZvel(i, zvel); hitscan(srcvect, s->sectnum, sintable[(sa+512)&2047], @@ -818,7 +823,7 @@ static void Proj_HandleKnee(hitdata_t *hit, int32_t i, int32_t p, int32_t atwith } } -int32_t A_Shoot(int32_t i, int32_t atwith) +int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel) { int16_t l, sa, j, k=-1; int32_t vel, zvel = 0, x, oldzvel; @@ -830,6 +835,16 @@ int32_t A_Shoot(int32_t i, int32_t atwith) const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1; DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; + if (override_zvel != SHOOT_HARDCODED_ZVEL) + { + use_actor_shootzvel = 1; + actor[i].shootzvel = override_zvel; + } + else + { + use_actor_shootzvel = 0; + } + if (s->picnum == APLAYER) { Bmemcpy(&srcvect,ps,sizeof(vec3_t)); @@ -1092,7 +1107,7 @@ int32_t A_Shoot(int32_t i, int32_t atwith) if (numplayers > 1 && g_netClient) return -1; - if (actor[i].shootzvel) zvel = actor[i].shootzvel; + zvel = A_GetShootZvel(i, zvel); j = A_InsertSprite(sect, srcvect.x+(sintable[(348+sa+512)&2047]/proj->offset), srcvect.y+(sintable[(sa+348)&2047]/proj->offset), @@ -1273,8 +1288,9 @@ int32_t A_Shoot(int32_t i, int32_t atwith) hit.pos.x = safeldist(g_player[j].ps->i, s); zvel = ((g_player[j].ps->opos.z - srcvect.z + (3<<8))*vel) / hit.pos.x; } - if (actor[i].shootzvel) zvel = actor[i].shootzvel; - oldzvel = zvel; + + zvel = A_GetShootZvel(i, zvel); + oldzvel = zvel; // NOTE: assigned to after last store to zvel, so redundant if (atwith == SPIT) { @@ -1367,7 +1383,7 @@ int32_t A_Shoot(int32_t i, int32_t atwith) if (numplayers > 1 && g_netClient) return -1; - if (actor[i].shootzvel) zvel = actor[i].shootzvel; + zvel = A_GetShootZvel(i, zvel); j = A_InsertSprite(sect, srcvect.x+(sintable[(348+sa+512)&2047]/448), srcvect.y+(sintable[(sa+348)&2047]/448), @@ -1527,7 +1543,8 @@ int32_t A_Shoot(int32_t i, int32_t atwith) if (zvel < -4096) zvel = -2048; vel = x>>4; - if (actor[i].shootzvel) zvel = actor[i].shootzvel; + + zvel = A_GetShootZvel(i, zvel); A_InsertSprite(sect, srcvect.x+(sintable[(512+sa+512)&2047]>>8), srcvect.y+(sintable[(sa+512)&2047]>>8), @@ -1619,7 +1636,8 @@ int32_t A_Shoot(int32_t i, int32_t atwith) zvel = ((g_player[j].ps->opos.z-srcvect.z)*512) / l ; } else zvel = 0; - if (actor[i].shootzvel) zvel = actor[i].shootzvel; + + zvel = A_GetShootZvel(i, zvel); j = A_InsertSprite(sect, srcvect.x+(sintable[(512+sa+512)&2047]>>12), srcvect.y+(sintable[(sa+512)&2047]>>12), @@ -1628,10 +1646,10 @@ int32_t A_Shoot(int32_t i, int32_t atwith) sprite[j].cstat = 128; sprite[j].clipdist = 32; - return j; } } + return -1; } diff --git a/polymer/eduke32/source/player.h b/polymer/eduke32/source/player.h index 8520980b6..74e3dda89 100644 --- a/polymer/eduke32/source/player.h +++ b/polymer/eduke32/source/player.h @@ -332,8 +332,15 @@ extern int32_t lastvisinc; extern int32_t mouseyaxismode; extern int32_t ticrandomseed; +#define SHOOT_HARDCODED_ZVEL INT32_MIN + +int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel); +static inline int32_t A_Shoot(int32_t i, int32_t atwith) +{ + return A_ShootWithZvel(i, atwith, SHOOT_HARDCODED_ZVEL); +} + int32_t A_GetHitscanRange(int32_t i); -int32_t A_Shoot(int32_t i,int32_t atwith); void getinput(int32_t snum); void P_AddAmmo(int32_t weapon,DukePlayer_t *p,int32_t amount); void P_AddWeapon(DukePlayer_t *p,int32_t weapon);