- scriptified viewscreen and camera.

This commit is contained in:
Christoph Oelckers 2022-01-21 01:04:08 +01:00
parent 046ba1ae0c
commit dee33ba4dd
28 changed files with 297 additions and 232 deletions

View file

@ -1363,49 +1363,6 @@ void reactor(DDukeActor* const actor, int REACTOR, int REACTOR2, int REACTORBURN
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void camera(DDukeActor *actor)
{
if (actor->temp_data[0] == 0)
{
actor->temp_data[1] += 8;
if (gs.camerashitable)
{
if (fi.ifhitbyweapon(actor) >= 0)
{
actor->temp_data[0] = 1; // static
actor->spr.cstat = CSTAT_SPRITE_INVISIBLE;
for (int x = 0; x < 5; x++)
RANDOMSCRAP(actor);
return;
}
}
if (actor->spr.hitag > 0)
{
auto const angle = mapangle(8);
if (actor->temp_data[1] < actor->spr.hitag)
actor->spr.angle += angle;
else if (actor->temp_data[1] < (actor->spr.hitag * 3))
actor->spr.angle -= angle;
else if (actor->temp_data[1] < (actor->spr.hitag << 2))
actor->spr.angle += angle;
else
{
actor->spr.angle += angle;
actor->temp_data[1] = 0;
}
}
}
}
//---------------------------------------------------------------------------
//
//

View file

@ -790,38 +790,7 @@ void movefallers_d(void)
//---------------------------------------------------------------------------
//
// split out of movestandables
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void moveviewscreen(DDukeActor* actor)
{
const double VIEWSCR_DIST = 1024; // was originally 2048, was increased to 8192 by EDuke32 and RedNukem, but with high resolutions the resulting 512 map units are still too low.
if (actor->spr.scale.X == 0) deletesprite(actor);
else
{
double a;
int p = findplayer(actor, &a);
double x = (actor->spr.pos - ps[p].GetActor()->spr.pos).Length(); // the result from findplayer is not really useful.
if (x >= VIEWSCR_DIST && camsprite == actor)
{
camsprite = nullptr;
actor->spr.yint = 0;
actor->temp_data[0] = 0;
}
}
}
//---------------------------------------------------------------------------
//
// this has been broken up into lots of smaller subfunctions
//
//---------------------------------------------------------------------------
@ -844,11 +813,6 @@ void movestandables_d(void)
continue;
}
else if (picnum == VIEWSCREEN || picnum == VIEWSCREEN2)
{
moveviewscreen(act);
}
else if (isIn(picnum, CANWITHSOMETHING, CANWITHSOMETHING2, CANWITHSOMETHING3, CANWITHSOMETHING4))
{
movecanwithsomething(act);
@ -2367,8 +2331,11 @@ void moveactors_d(void)
int *t = &act->temp_data[0];
switch (act->spr.picnum)
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
}
else switch (act->spr.picnum)
{
case FLAMETHROWERFLAME:
if (isWorldTour()) flamethrowerflame(act);
@ -2495,10 +2462,6 @@ void moveactors_d(void)
case REACTOR2:
reactor(act, REACTOR, REACTOR2, REACTORBURNT, REACTOR2BURNT, REACTORSPARK, REACTOR2SPARK);
continue;
case CAMERA1:
camera(act);
continue;
}

View file

@ -2481,7 +2481,11 @@ void moveactors_r(void)
auto sectp = act->sector();
switch(act->spr.picnum)
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallTick(act);
}
else switch(act->spr.picnum)
{
case RESPAWNMARKERRED:
case RESPAWNMARKERYELLOW:
@ -2684,10 +2688,6 @@ void moveactors_r(void)
case REACTOR2:
reactor(act, REACTOR, REACTOR2, REACTORBURNT, REACTOR2BURNT, REACTORSPARK, REACTOR2SPARK);
continue;
case CAMERA1:
camera(act);
continue;
}

View file

@ -177,10 +177,13 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
t->angle = h->interpolatedangle(interpfrac);
}
auto sectp = h->sector();
if (h->GetClass() != RUNTIME_CLASS(DDukeActor))
{
bool res = CallAnimate(h, t);
if (actorflag(h, SFLAG2_ALWAYSROTATE1))
applyRotation1(h, t, viewang);
if (sectp->floorpal && !actorflag(h, SFLAG2_NOFLOORPAL))
copyfloorpal(t, sectp);
@ -246,21 +249,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
case CRYSTALAMMO:
t->shade = int(BobVal(PlayClock << 4) * 16);
continue;
case VIEWSCREEN:
case VIEWSCREEN2:
if (camsprite != nullptr && h->GetHitOwner() && h->GetHitOwner()->temp_data[0] == 1)
{
t->picnum = STATIC;
t->cstat |= randomFlip();
t->scale.X += (0.125);
t->scale.Y += (0.125);
}
else if (camsprite && camsprite == h->GetHitOwner())
{
t->picnum = TILE_VIEWSCR;
}
break;
case SHRINKSPARK:
t->picnum = SHRINKSPARK + ((PlayClock >> 4) & 3);
break;
@ -685,7 +673,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
}
break;
case CAMERA1:
case RAT:
if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal))
{

View file

@ -157,10 +157,13 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
t->angle = h->interpolatedangle(interpfrac);
}
auto sectp = h->sector();
if (h->GetClass() != RUNTIME_CLASS(DDukeActor))
{
bool res = CallAnimate(h, t);
if (actorflag(h, SFLAG2_ALWAYSROTATE1))
applyRotation1(h, t, viewang);
if (sectp->floorpal && !actorflag(h, SFLAG2_NOFLOORPAL))
copyfloorpal(t, sectp);
@ -920,7 +923,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
}
break;
case CAMERA1:
case RAT:
k = angletorotation1(t->angle, viewang);
if (k > 4)

View file

@ -360,6 +360,7 @@ enum sflags2_t
SFLAG2_DONTANIMATE = 0x00000200,
SFLAG2_INTERPOLATEANGLE = 0x00000400,
SFLAG2_GREENBLOOD = 0x00000800,
SFLAG2_ALWAYSROTATE1 = 0x00001000,
};
using EDukeFlags2 = TFlags<sflags2_t, uint32_t>;

View file

@ -116,10 +116,11 @@ extern Dispatcher fi;
void CallInitialize(DDukeActor* actor);
void CallTick(DDukeActor* actor);
bool CallOperate(DDukeActor* actor, int plnum);
void CallAction(DDukeActor* actor);
void CallOnHit(DDukeActor* actor, DDukeActor* hitter);
void CallOnHurt(DDukeActor* actor, player_struct* hitter);
void CallOnUse(DDukeActor* actor, player_struct* user);
bool CallOnUse(DDukeActor* actor, player_struct* user);
bool CallAnimate(DDukeActor* actor, tspritetype* hitter);

View file

@ -225,6 +225,7 @@ void initactorflags_d()
setflag(SFLAG2_DONTANIMATE, { TRIPBOMB, LASERLINE });
setflag(SFLAG2_INTERPOLATEANGLE, { BEARINGPLATE });
setflag(SFLAG2_GREENBLOOD, { OOZFILTER, NEWBEAST });
setflag(SFLAG2_ALWAYSROTATE1, { RAT, CAMERA1 });
if (isWorldTour())
{

View file

@ -252,6 +252,7 @@ void initactorflags_r()
if (isRRRA()) setflag(SFLAG2_BREAKMIRRORS, { RPG2 });
setflag(SFLAG2_CAMERA, { CAMERA1 });
setflag(SFLAG2_GREENBLOOD, { OOZFILTER });
setflag(SFLAG2_ALWAYSROTATE1, { RAT, CAMERA1 });
// Animals were not supposed to have this, but due to a coding bug the logic was unconditional for everything in the game.
for (auto& ainf : gs.actorinfo)

View file

@ -29,7 +29,7 @@ void movefx();
void moveclouds(double interpfrac);
void movefta();
void clearcameras(int i, player_struct* p);
void clearcameras(player_struct* p);
void RANDOMSCRAP(DDukeActor* i);
void detonate(DDukeActor* i, int explosion);
void movecanwithsomething(DDukeActor* i);
@ -44,7 +44,6 @@ void forcesphere(DDukeActor* i, int forcesphere);
void recon(DDukeActor* i, int explosion, int firelaser, int attacksnd, int painsnd, int roamsnd, int shift, int (*getspawn)(DDukeActor* i));
void ooz(DDukeActor* i);
void reactor(DDukeActor* i, int REACTOR, int REACTOR2, int REACTORBURNT, int REACTOR2BURNT, int REACTORSPARK, int REACTOR2SPARK);
void camera(DDukeActor* i);
void bloodsplats(DDukeActor* actor);
void forcesphereexplode(DDukeActor* i);
void watersplash2(DDukeActor* i);

View file

@ -446,13 +446,16 @@ void CallOnHurt(DDukeActor* actor, player_struct* hitter)
void CallOnUse(DDukeActor* actor, player_struct* user)
bool CallOnUse(DDukeActor* actor, player_struct* user)
{
int nval = false;
IFVIRTUALPTR(actor, DDukeActor, onUse)
{
VMValue val[2] = { actor, user };
VMCall(func, val, 2, nullptr, 0);
VMReturn ret(&nval);
VMCall(func, val, 2, &ret, 1);
}
return nval;
}
bool CallAnimate(DDukeActor* actor, tspritetype* tspr)
@ -461,8 +464,8 @@ bool CallAnimate(DDukeActor* actor, tspritetype* tspr)
IFVIRTUALPTR(actor, DDukeActor, animate)
{
VMReturn ret(& nval);
VMValue val[2] = { actor, tspr };
VMCall(func, val, 2, &ret, 1);
VMValue val[3] = { actor, tspr };
VMCall(func, val, 3, &ret, 1);
}
return nval;
}

View file

@ -2,6 +2,7 @@
#include "gamehud.h"
#include "global.h"
#include "models/modeldata.h"
// all inline functions.
BEGIN_DUKE_NS
@ -244,4 +245,22 @@ inline int angletorotation2(DAngle sprang, DAngle viewang)
return ((sprang.Buildang() + 3072 + 128 - viewang.Buildang()) & 2047) / 170;
}
inline void applyRotation1(DDukeActor* h, tspritetype* t, DAngle viewang)
{
if (hw_models && modelManager.CheckModel(h->spr.picnum, h->spr.pal))
{
t->cstat &= ~CSTAT_SPRITE_XFLIP;
return;
}
int k = angletorotation1(t->angle, viewang);
if (k > 4)
{
k = 8 - k;
t->cstat |= CSTAT_SPRITE_XFLIP;
}
else t->cstat &= ~CSTAT_SPRITE_XFLIP;
t->picnum = h->spr.picnum + k;
}
END_DUKE_NS

View file

@ -849,4 +849,5 @@ x(DEVELOPERCOMMENTARY, 5294)
x(BOSS5, 5310)
x(BOSS5STAYPUT, 5311)
x(SERIOUSSAM, 5846)
x(VIEWSCR, 30715) // MAXTILES-5

View file

@ -1434,3 +1434,4 @@ x(MAMACLOUD, 8663)
x(MAMA, 8705)
x(MAMAJIBA, 8890)
x(MAMAJIBB, 8895)
x(VIEWSCR, 30715) // MAXTILES-5

View file

@ -158,7 +158,6 @@ static void cachespritenum(DDukeActor* actor)
maxc = 3;
break;
case NUKEBARREL:
case CAMERA1:
maxc = 5;
break;
}

View file

@ -266,7 +266,6 @@ static void cachespritenum(DDukeActor* actor)
maxc = 3;
break;
case NUKEBARREL:
case CAMERA1:
maxc = 5;
break;
case VIXEN:

View file

@ -1438,23 +1438,18 @@ void checkhitsprite_d(DDukeActor* targ, DDukeActor* proj)
//
//---------------------------------------------------------------------------
void clearcameras(int i, player_struct* p)
void clearcameras(player_struct* p)
{
if (i < 0)
p->restorexyz();
p->newOwner = nullptr;
updatesector(p->pos, &p->cursector);
DukeStatIterator it(STAT_ACTOR);
while (auto act = it.Next())
{
p->restorexyz();
p->newOwner = nullptr;
updatesector(p->pos, &p->cursector);
DukeStatIterator it(STAT_ACTOR);
while (auto act = it.Next())
{
if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0;
}
if (actorflag(act, SFLAG2_CAMERA)) act->spr.yint = 0;
}
else if (p->newOwner != nullptr)
p->newOwner = nullptr;
}
//---------------------------------------------------------------------------
@ -1515,7 +1510,7 @@ void checksectors_d(int snum)
{
if (abs(PlayerInputSideVel(snum)) > 1.5 || abs(PlayerInputForwardVel(snum)) > 1.5)
{
clearcameras(-1, p);
clearcameras(p);
return;
}
}
@ -1530,7 +1525,7 @@ void checksectors_d(int snum)
{
if (p->newOwner != nullptr)
{
clearcameras(-1, p);
clearcameras(p);
}
return;
}
@ -1616,91 +1611,67 @@ void checksectors_d(int snum)
if (neartagsprite->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallOnUse(neartagsprite, p);
if (CallOnUse(neartagsprite, p))
return;
}
else
switch (neartagsprite->spr.picnum)
{
case TOILET:
case STALL:
if (p->last_pissed_time == 0)
switch (neartagsprite->spr.picnum)
{
S_PlayActorSound(DUKE_URINATE, p->GetActor());
case TOILET:
case STALL:
if (p->last_pissed_time == 0)
{
S_PlayActorSound(DUKE_URINATE, p->GetActor());
p->last_pissed_time = 26 * 220;
p->transporter_hold = 29 * 2;
if (p->holster_weapon == 0)
{
p->holster_weapon = 1;
p->weapon_pos = -1;
p->last_pissed_time = 26 * 220;
p->transporter_hold = 29 * 2;
if (p->holster_weapon == 0)
{
p->holster_weapon = 1;
p->weapon_pos = -1;
}
if (p->GetActor()->spr.extra <= (gs.max_player_health - (gs.max_player_health / 10)))
{
p->GetActor()->spr.extra += gs.max_player_health / 10;
p->last_extra = p->GetActor()->spr.extra;
}
else if (p->GetActor()->spr.extra < gs.max_player_health)
p->GetActor()->spr.extra = gs.max_player_health;
}
if (p->GetActor()->spr.extra <= (gs.max_player_health - (gs.max_player_health / 10)))
{
p->GetActor()->spr.extra += gs.max_player_health / 10;
p->last_extra = p->GetActor()->spr.extra;
}
else if (p->GetActor()->spr.extra < gs.max_player_health)
p->GetActor()->spr.extra = gs.max_player_health;
}
else if (S_CheckActorSoundPlaying(neartagsprite, FLUSH_TOILET) == 0)
S_PlayActorSound(FLUSH_TOILET, neartagsprite);
return;
else if (S_CheckActorSoundPlaying(neartagsprite, FLUSH_TOILET) == 0)
S_PlayActorSound(FLUSH_TOILET, neartagsprite);
return;
case NUKEBUTTON:
{
walltype* wal;
hitawall(p, &wal);
if (wal != nullptr && wal->overpicnum == 0)
if (neartagsprite->temp_data[0] == 0)
{
neartagsprite->temp_data[0] = 1;
neartagsprite->SetOwner(p->GetActor());
p->buttonpalette = neartagsprite->spr.pal;
if (p->buttonpalette)
ud.secretlevel = neartagsprite->spr.lotag;
else ud.secretlevel = 0;
}
return;
}
case PLUG:
S_PlayActorSound(SHORT_CIRCUIT, pact);
p->GetActor()->spr.extra -= 2 + (krand() & 3);
SetPlayerPal(p, PalEntry(32, 48, 48, 64));
break;
case VIEWSCREEN:
case VIEWSCREEN2:
{
i = 0;
DukeStatIterator it(STAT_ACTOR);
while (auto acti = it.Next())
case NUKEBUTTON:
{
if (actorflag(acti, SFLAG2_CAMERA) && acti->spr.yint == 0 && neartagsprite->spr.hitag == acti->spr.lotag)
{
acti->spr.yint = 1; //Using this camera
if (snum == screenpeek) S_PlaySound(MONITOR_ACTIVE);
neartagsprite->SetOwner(acti);
neartagsprite->spr.yint = 1;
camsprite = neartagsprite;
p->newOwner = acti;
return;
}
walltype* wal;
hitawall(p, &wal);
if (wal != nullptr && wal->overpicnum == 0)
if (neartagsprite->temp_data[0] == 0)
{
neartagsprite->temp_data[0] = 1;
neartagsprite->SetOwner(p->GetActor());
p->buttonpalette = neartagsprite->spr.pal;
if (p->buttonpalette)
ud.secretlevel = neartagsprite->spr.lotag;
else ud.secretlevel = 0;
}
return;
}
i = -1;
}
clearcameras(i, p);
return;
case PLUG:
S_PlayActorSound(SHORT_CIRCUIT, pact);
p->GetActor()->spr.extra -= 2 + (krand() & 3);
SetPlayerPal(p, PalEntry(32, 48, 48, 64));
break;
}
}
}
if (!PlayerInput(snum, SB_OPEN)) return;
else if (p->newOwner != nullptr)
else if (p->newOwner != nullptr)
{
clearcameras(-1, p);
clearcameras(p);
return;
}
}
if (near.hitWall == nullptr && near.hitSector == nullptr && near.actor() == nullptr)
if (hits(p->GetActor()) < 32)
@ -1721,7 +1692,7 @@ void checksectors_d(int snum)
}
else if (p->newOwner != nullptr)
{
clearcameras(-1, p);
clearcameras(p);
return;
}
}

View file

@ -2552,7 +2552,8 @@ void checksectors_r(int snum)
if (neartagsprite->GetClass() != RUNTIME_CLASS(DDukeActor))
{
CallOnUse(neartagsprite, p);
if (CallOnUse(neartagsprite, p))
return;
}
else
switch (neartagsprite->spr.picnum)

View file

@ -515,14 +515,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
ChangeActorStat(act, STAT_MISC);
break;
case VIEWSCREEN:
case VIEWSCREEN2:
act->SetOwner(act);
act->spr.lotag = 1;
act->spr.extra = 1;
ChangeActorStat(act, STAT_STANDABLE);
break;
case SHELL: //From the player
case SHOTGUNSHELL:
initshell(actj, act, act->spr.picnum == SHELL);
@ -965,11 +957,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
ChangeActorStat(act, STAT_ZOMBIEACTOR);
break;
case CAMERA1:
case CAMERA1 + 1:
case CAMERA1 + 2:
case CAMERA1 + 3:
case CAMERA1 + 4:
case CAMERAPOLE:
act->spr.extra = 1;
@ -986,9 +973,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
break;
}
else act->spr.pal = 0;
if (act->spr.picnum == CAMERAPOLE || act->spr.picnum == GENERICPOLE) break;
act->spr.picnum = CAMERA1;
ChangeActorStat(act, STAT_ACTOR);
break;
case STEAM:
if (actj)

View file

@ -1201,11 +1201,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
}
act->spr.shade = act->sector()->floorshade;
break;
case CAMERA1:
case CAMERA1 + 1:
case CAMERA1 + 2:
case CAMERA1 + 3:
case CAMERA1 + 4:
case CAMERAPOLE:
act->spr.extra = 1;
@ -1219,9 +1214,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
break;
}
else act->spr.pal = 0;
if (act->spr.picnum == CAMERAPOLE) break;
act->spr.picnum = CAMERA1;
ChangeActorStat(act, STAT_ACTOR);
break;
case STEAM:
if (actj)

View file

@ -108,6 +108,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, global_random, duke_global_random)
}
DEFINE_GLOBAL_UNSIZED(dlevel)
DEFINE_GLOBAL(camsprite)
//---------------------------------------------------------------------------
//
@ -694,6 +695,14 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, angle, dukeplayer_angle)
ACTION_RETURN_FLOAT(dukeplayer_angle(self));
}
DEFINE_ACTION_FUNCTION_NATIVE(_DukePlayer, clearcameras, clearcameras)
{
PARAM_SELF_STRUCT_PROLOGUE(player_struct);
clearcameras(self);
return 0;
}
static DDukeActor* duke_firstStat(DukeStatIterator* it, int statnum)
{
it->Reset(statnum);

View file

@ -26,6 +26,14 @@ spawnclasses
916 = DukeFireext
1079 = DukeOozFilter
1247 = DukeSeenine
502 = DukeViewscreen
499 = DukeViewscreen2
621 = DukeCamera // yes, they are all the same!
622 = DukeCamera
623 = DukeCamera
624 = DukeCamera
625 = DukeCamera
1272 = DukeTrash
634 = DukeBolt1
635 = DukeBolt2

View file

@ -65,6 +65,7 @@ version "4.10"
#include "zscript/games/duke/actors/bolt.zs"
#include "zscript/games/duke/actors/waterdrip.zs"
#include "zscript/games/duke/actors/doorshock.zs"
#include "zscript/games/duke/actors/viewscreen.zs"
#include "zscript/games/blood/bloodgame.zs"
#include "zscript/games/blood/ui/menu.zs"

View file

@ -56,4 +56,15 @@ class CoreActor native
native void backuppos();
native void setPosition(Vector3 pos);
native void setPositionZ(Vector3 pos);
int randomFlip()
{
int r = random(0, 3);
if (r == 0) return 0;
if (r == 1) return CSTAT_SPRITE_XFLIP;
if (r == 2) return CSTAT_SPRITE_YFLIP;
return CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP;
}
}

View file

@ -0,0 +1,151 @@
class DukeViewscreen : DukeActor
{
default
{
lotag 1;
extra 1;
statnum STAT_STANDABLE;
spriteset "VIEWSCREEN", "STATIC", "VIEWSCR";
}
const VIEWSCR_DIST = 1024; // was originally 2048, was increased to 8192 by EDuke32 and RedNukem, but with high resolutions the resulting 512 map units are still too low.
override void Initialize()
{
self.ownerActor = self;
}
override void Tick()
{
if (self.scale.X == 0) self.Destroy();
else
{
let p = self.findplayer();
double x = (self.pos - p.actor.pos).LengthSquared(); // the result from findplayer is not really useful.
if (x >= VIEWSCR_DIST * VIEWSCR_DIST && camsprite == self)
{
camsprite = null;
self.yint = 0;
self.temp_data[0] = 0;
}
}
}
override bool onUse(DukePlayer user)
{
DukeStatIterator it;
for(let acti = it.First(STAT_ACTOR); acti; acti = it.Next())
{
if (acti.actorflag2(SFLAG2_CAMERA) && acti.yint == 0 && self.hitag == acti.lotag)
{
acti.yint = 1; //Using this camera
if (user == Duke.GetViewPlayer()) Duke.PlaySound(DukeSnd.MONITOR_ACTIVE);
self.ownerActor = acti;
self.yint = 1;
camsprite = self;
user.newOwner = acti;
return true;
}
}
user.clearcameras();
return true;
}
override bool animate(tspritetype tspr)
{
let actor = DukeActor(tspr.ownerActor);
let hitowner = actor.hitOwnerActor;
if (camsprite != null && hitowner && hitowner.temp_data[0] == 1)
{
tspr.SetSpritePic(self, 1);
tspr.cstat &= ~ (CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP);
tspr.cstat |= randomFlip();
tspr.scale.X += (0.125);
tspr.scale.Y += (0.125);
}
else if (camsprite && camsprite == hitowner)
{
tspr.SetSpritePic(self, 2);
}
return true;
}
}
class DukeViewscreen2 : DukeViewscreen
{
default
{
spriteset "VIEWSCREEN", "STATIC", "VIEWSCR";
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeCamera : DukeActor
{
default
{
pic "CAMERA1";
statnum STAT_ACTOR;
extra 1;
}
override void Initialize()
{
if (gs.camerashitable) self.cstat = CSTAT_SPRITE_BLOCK_ALL;
else self.cstat = 0;
if (ud.multimode < 2 && self.pal != 0)
{
self.scale = (0, 0);
self.ChangeStat(STAT_MISC);
return;
}
else self.pal = 0;
}
override void Tick()
{
if (self.temp_data[0] == 0)
{
self.temp_data[1] += 8;
if (gs.camerashitable)
{
int j = self.ifhitbyweapon();
if (j >= 0)
{
self.temp_data[0] = 1; // static
self.cstat = CSTAT_SPRITE_INVISIBLE;
for (int x = 0; x < 5; x++)
self.RANDOMSCRAP();
return;
}
}
if (self.hitag > 0)
{
let angle = 360. / 256;
if (self.temp_data[1] < self.hitag)
self.angle += angle;
else if (self.temp_data[1] < (self.hitag * 3))
self.angle -= angle;
else if (self.temp_data[1] < (self.hitag * 4))
self.angle += angle;
else
{
self.angle += angle;
self.temp_data[1] = 0;
}
}
}
}
}

View file

@ -69,7 +69,7 @@ class DukeWaterFountain : DukeActor
}
}
override void onUse(DukePlayer user)
override bool onUse(DukePlayer user)
{
if (self.temp_data[0] != 1)
{
@ -83,6 +83,7 @@ class DukeWaterFountain : DukeActor
act.PlayActorSound(DukeSnd.DUKE_DRINKING);
}
}
return true;
}
}

View file

@ -140,7 +140,7 @@ class DukeActor : CoreActor native
virtual void Tick() {}
virtual void onHit(DukeActor hitter) { checkhitdefault(hitter); }
virtual void onHurt(DukePlayer p) {}
virtual void onUse(DukePlayer user) {}
virtual bool onUse(DukePlayer user) { return false; }
virtual bool animate(tspritetype tspr) { return false; }
virtual void RunState() {} // this is the CON function.
@ -165,6 +165,7 @@ extend struct _
native @DukeGameInfo gs;
native @DukeUserDefs ud;
native DukeLevel dlevel;
native DukeActor camsprite;
}
// The level struct is a wrapper to group all level related global variables and static functions into one object.

View file

@ -280,6 +280,7 @@ struct DukePlayer native
native void addpos(Vector3 pos);
native void settargetangle(double angle, bool backup = false);
native double angle();
native void clearcameras();
}