Merge remote-tracking branch 'remotes/gzdoom/master'

This commit is contained in:
Rachael Alexanderson 2017-02-15 05:43:15 -05:00
commit 5dad292c56
26 changed files with 327 additions and 70 deletions

View file

@ -1230,6 +1230,7 @@ public:
bool InStateSequence(FState * newstate, FState * basestate); bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate); int GetTics(FState * newstate);
bool SetState (FState *newstate, bool nofunction=false); bool SetState (FState *newstate, bool nofunction=false);
virtual void SplashCheck();
virtual bool UpdateWaterLevel (bool splash=true); virtual bool UpdateWaterLevel (bool splash=true);
bool isFast(); bool isFast();
bool isSlow(); bool isSlow();

View file

@ -2835,10 +2835,10 @@ void FStartupScreen::NetMessage(char const *,...) {}
void FStartupScreen::NetDone(void) {} void FStartupScreen::NetDone(void) {}
bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; } bool FStartupScreen::NetLoop(bool (*)(void *),void *) { return false; }
DEFINE_FIELD_X(InputEvent, event_t, type) DEFINE_FIELD_X(InputEventData, event_t, type)
DEFINE_FIELD_X(InputEvent, event_t, subtype) DEFINE_FIELD_X(InputEventData, event_t, subtype)
DEFINE_FIELD_X(InputEvent, event_t, data1) DEFINE_FIELD_X(InputEventData, event_t, data1)
DEFINE_FIELD_X(InputEvent, event_t, data2) DEFINE_FIELD_X(InputEventData, event_t, data2)
DEFINE_FIELD_X(InputEvent, event_t, data3) DEFINE_FIELD_X(InputEventData, event_t, data3)
DEFINE_FIELD_X(InputEvent, event_t, x) DEFINE_FIELD_X(InputEventData, event_t, x)
DEFINE_FIELD_X(InputEvent, event_t, y) DEFINE_FIELD_X(InputEventData, event_t, y)

View file

@ -164,7 +164,7 @@ static void E_InitStaticHandler(PClass* type, FString typestring, bool map)
{ {
if (type == nullptr) if (type == nullptr)
{ {
I_Error("Fatal: unknown event handler class %s in MAPINFO!\n", TEXTCOLOR_ESCAPE, typestring.GetChars()); I_Error("Fatal: unknown event handler class %s in MAPINFO!\n", typestring.GetChars());
return; return;
} }
@ -1033,7 +1033,7 @@ static DConsoleEvent* E_SetupConsoleEvent()
if (!e) e = (DConsoleEvent*)RUNTIME_CLASS(DConsoleEvent)->CreateNew(); if (!e) e = (DConsoleEvent*)RUNTIME_CLASS(DConsoleEvent)->CreateNew();
e->Player = -1; e->Player = -1;
e->Name = ""; e->Name = "";
for (int i = 0; i < countof(e->Args); i++) for (size_t i = 0; i < countof(e->Args); i++)
e->Args[i] = 0; e->Args[i] = 0;
return e; return e;
} }

View file

@ -1442,7 +1442,7 @@ class CommandDrawNumber : public CommandDrawString
int retv; int retv;
VMReturn ret(&retv); VMReturn ret(&retv);
GlobalVMStack.Call(func, params, 2, &ret, 1); GlobalVMStack.Call(func, params, 2, &ret, 1);
num = retv / TICRATE + 1; num = retv < 0? 0 : retv / TICRATE + 1;
break; break;
} }
case INVENTORY: case INVENTORY:

View file

@ -97,6 +97,28 @@ void gl_CreateSections();
void AdjustSpriteOffsets() void AdjustSpriteOffsets()
{ {
int lump, lastlump = 0; int lump, lastlump = 0;
int sprid;
TMap<int, bool> donotprocess;
int numtex = Wads.GetNumLumps();
for (int i = 0; i < numtex; i++)
{
if (Wads.GetLumpFile(i) > 1) break; // we are past the IWAD
if (Wads.GetLumpNamespace(i) == ns_sprites && Wads.GetLumpFile(i) == FWadCollection::IWAD_FILENUM)
{
char str[9];
Wads.GetLumpName(str, i);
FTextureID texid = TexMan.CheckForTexture(str, FTexture::TEX_Sprite, 0);
if (texid.isValid() && Wads.GetLumpFile(TexMan[texid]->SourceLump) > FWadCollection::IWAD_FILENUM)
{
// This texture has been replaced by some PWAD.
memcpy(&sprid, str, 4);
donotprocess[sprid] = true;
}
}
}
while ((lump = Wads.FindLump("SPROFS", &lastlump, false)) != -1) while ((lump = Wads.FindLump("SPROFS", &lastlump, false)) != -1)
{ {
FScanner sc; FScanner sc;
@ -108,6 +130,7 @@ void AdjustSpriteOffsets()
{ {
int x,y; int x,y;
bool iwadonly = false; bool iwadonly = false;
bool forced = false;
FTextureID texno = TexMan.CheckForTexture(sc.String, FTexture::TEX_Sprite); FTextureID texno = TexMan.CheckForTexture(sc.String, FTexture::TEX_Sprite);
sc.MustGetStringName(","); sc.MustGetStringName(",");
sc.MustGetNumber(); sc.MustGetNumber();
@ -119,6 +142,7 @@ void AdjustSpriteOffsets()
{ {
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("iwad")) iwadonly = true; if (sc.Compare("iwad")) iwadonly = true;
if (sc.Compare("iwadforced")) forced = iwadonly = true;
} }
if (texno.isValid()) if (texno.isValid())
{ {
@ -131,6 +155,11 @@ void AdjustSpriteOffsets()
int wadno = Wads.GetLumpFile(lumpnum); int wadno = Wads.GetLumpFile(lumpnum);
if ((iwadonly && wadno==FWadCollection::IWAD_FILENUM) || (!iwadonly && wadno == ofslumpno)) if ((iwadonly && wadno==FWadCollection::IWAD_FILENUM) || (!iwadonly && wadno == ofslumpno))
{ {
if (wadno == FWadCollection::IWAD_FILENUM && !forced && iwadonly)
{
memcpy(&sprid, &tex->Name[0], 4);
if (donotprocess.CheckKey(sprid)) continue; // do not alter sprites that only get partially replaced.
}
tex->LeftOffset=x; tex->LeftOffset=x;
tex->TopOffset=y; tex->TopOffset=y;
tex->KillNative(); tex->KillNative();

View file

@ -1021,7 +1021,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlaySound)
if (!looping) if (!looping)
{ {
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local); if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
}
} }
else else
{ {

View file

@ -5287,6 +5287,14 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end,
if (P_ActivateThingSpecial(in->d.thing, usething)) if (P_ActivateThingSpecial(in->d.thing, usething))
return true; return true;
} }
IFVIRTUALPTR(usething, AActor, Used)
{
VMValue params[] = { usething, in->d.thing };
int ret;
VMReturn vret(&ret);
GlobalVMStack.Call(func, params, 2, &vret, 1);
if (ret) return true;
}
continue; continue;
} }

View file

@ -4540,23 +4540,22 @@ void AActor::CheckSectorTransition(sector_t *oldsec)
//========================================================================== //==========================================================================
// //
// AActor::UpdateWaterLevel // AActor::SplashCheck
// //
// Returns true if actor should splash // Returns true if actor should splash
// //
//========================================================================== //==========================================================================
bool AActor::UpdateWaterLevel (bool dosplash) void AActor::SplashCheck()
{ {
BYTE lastwaterlevel = waterlevel;
double fh = -FLT_MAX; double fh = -FLT_MAX;
bool reset=false; bool reset = false;
waterlevel = 0; waterlevel = 0;
if (Sector == NULL) if (Sector == NULL)
{ {
return false; return;
} }
if (Sector->MoreFlags & SECF_UNDERWATER) // intentionally not SECF_UNDERWATERMASK if (Sector->MoreFlags & SECF_UNDERWATER) // intentionally not SECF_UNDERWATERMASK
@ -4568,7 +4567,7 @@ bool AActor::UpdateWaterLevel (bool dosplash)
const sector_t *hsec = Sector->GetHeightSec(); const sector_t *hsec = Sector->GetHeightSec();
if (hsec != NULL) if (hsec != NULL)
{ {
fh = hsec->floorplane.ZatPoint (this); fh = hsec->floorplane.ZatPoint(this);
//if (hsec->MoreFlags & SECF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors //if (hsec->MoreFlags & SECF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors
{ {
if (Z() < fh) if (Z() < fh)
@ -4584,7 +4583,7 @@ bool AActor::UpdateWaterLevel (bool dosplash)
} }
} }
} }
else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint (this))) else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this)))
{ {
waterlevel = 3; waterlevel = 3;
} }
@ -4593,29 +4592,23 @@ bool AActor::UpdateWaterLevel (bool dosplash)
waterlevel = 0; waterlevel = 0;
} }
} }
// even non-swimmable deep water must be checked here to do the splashes correctly
// But the water level must be reset when this function returns
if (!(hsec->MoreFlags&SECF_UNDERWATERMASK))
{
reset = true;
}
} }
else else
{ {
// Check 3D floors as well! // Check 3D floors as well!
for(auto rover : Sector->e->XFloor.ffloors) for (auto rover : Sector->e->XFloor.ffloors)
{ {
if (!(rover->flags & FF_EXISTS)) continue; if (!(rover->flags & FF_EXISTS)) continue;
if (rover->flags & FF_SOLID) continue; if (rover->flags & FF_SOLID) continue;
reset = !(rover->flags & FF_SWIMMABLE); bool reset = !(rover->flags & FF_SWIMMABLE);
if (reset && rover->alpha == 0) continue; if (reset && rover->alpha == 0) continue;
double ff_bottom=rover->bottom.plane->ZatPoint(this); double ff_bottom = rover->bottom.plane->ZatPoint(this);
double ff_top=rover->top.plane->ZatPoint(this); double ff_top = rover->top.plane->ZatPoint(this);
if(ff_top <= Z() || ff_bottom > (Center())) continue; if (ff_top <= Z() || ff_bottom > (Center())) continue;
fh=ff_top; fh = ff_top;
if (Z() < fh) if (Z() < fh)
{ {
waterlevel = 1; waterlevel = 1;
@ -4637,14 +4630,103 @@ bool AActor::UpdateWaterLevel (bool dosplash)
// some additional checks to make deep sectors like Boom's splash without setting // some additional checks to make deep sectors like Boom's splash without setting
// the water flags. // the water flags.
if (boomwaterlevel == 0 && waterlevel != 0 && dosplash) if (boomwaterlevel == 0 && waterlevel != 0)
{ {
P_HitWater(this, Sector, PosAtZ(fh), true); P_HitWater(this, Sector, PosAtZ(fh), true);
} }
boomwaterlevel = waterlevel; boomwaterlevel = waterlevel;
if (reset) return;
}
//==========================================================================
//
// AActor::UpdateWaterLevel
//
// Returns true if actor should splash
//
//==========================================================================
bool AActor::UpdateWaterLevel(bool dosplash)
{
if (dosplash) SplashCheck();
double fh = -FLT_MAX;
bool reset = false;
waterlevel = 0;
if (Sector == NULL)
{ {
waterlevel = lastwaterlevel; return false;
}
if (Sector->MoreFlags & SECF_UNDERWATER) // intentionally not SECF_UNDERWATERMASK
{
waterlevel = 3;
}
else
{
const sector_t *hsec = Sector->GetHeightSec();
if (hsec != NULL)
{
fh = hsec->floorplane.ZatPoint(this);
if (hsec->MoreFlags & SECF_UNDERWATERMASK) // also check Boom-style non-swimmable sectors
{
if (Z() < fh)
{
waterlevel = 1;
if (Center() < fh)
{
waterlevel = 2;
if ((player && Z() + player->viewheight <= fh) ||
(Top() <= fh))
{
waterlevel = 3;
}
}
}
else if (!(hsec->MoreFlags & SECF_FAKEFLOORONLY) && (Top() > hsec->ceilingplane.ZatPoint(this)))
{
waterlevel = 3;
}
else
{
waterlevel = 0;
}
}
}
else
{
// Check 3D floors as well!
for (auto rover : Sector->e->XFloor.ffloors)
{
if (!(rover->flags & FF_EXISTS)) continue;
if (rover->flags & FF_SOLID) continue;
if (!(rover->flags & FF_SWIMMABLE)) continue;
double ff_bottom = rover->bottom.plane->ZatPoint(this);
double ff_top = rover->top.plane->ZatPoint(this);
if (ff_top <= Z() || ff_bottom > (Center())) continue;
fh = ff_top;
if (Z() < fh)
{
waterlevel = 1;
if (Center() < fh)
{
waterlevel = 2;
if ((player && Z() + player->viewheight <= fh) ||
(Top() <= fh))
{
waterlevel = 3;
}
}
}
break;
}
}
} }
return false; // we did the splash ourselves return false; // we did the splash ourselves
} }

View file

@ -118,8 +118,8 @@ void P_LoadTranslator(const char *lumpname);
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid = -1); void P_TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineindexforid = -1);
int P_TranslateSectorSpecial (int); int P_TranslateSectorSpecial (int);
int GetUDMFInt(int type, int index, const char *key); int GetUDMFInt(int type, int index, FName key);
double GetUDMFFloat(int type, int index, const char *key); double GetUDMFFloat(int type, int index, FName key);
bool P_LoadGLNodes(MapData * map); bool P_LoadGLNodes(MapData * map);
bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime); bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime);

View file

@ -342,7 +342,7 @@ FUDMFKey *FUDMFKeys::Find(FName key)
// //
//=========================================================================== //===========================================================================
int GetUDMFInt(int type, int index, const char *key) int GetUDMFInt(int type, int index, FName key)
{ {
assert(type >=0 && type <=3); assert(type >=0 && type <=3);
@ -359,7 +359,16 @@ int GetUDMFInt(int type, int index, const char *key)
return 0; return 0;
} }
double GetUDMFFloat(int type, int index, const char *key) DEFINE_ACTION_FUNCTION(FLevelLocals, GetUDMFInt)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_INT(type);
PARAM_INT(index);
PARAM_NAME(key);
ACTION_RETURN_INT(GetUDMFInt(type, index, key));
}
double GetUDMFFloat(int type, int index, FName key)
{ {
assert(type >=0 && type <=3); assert(type >=0 && type <=3);
@ -376,6 +385,41 @@ double GetUDMFFloat(int type, int index, const char *key)
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION(FLevelLocals, GetUDMFFloat)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_INT(type);
PARAM_INT(index);
PARAM_NAME(key);
ACTION_RETURN_FLOAT(GetUDMFFloat(type, index, key));
}
FString GetUDMFString(int type, int index, FName key)
{
assert(type >= 0 && type <= 3);
FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index);
if (pKeys != NULL)
{
FUDMFKey *pKey = pKeys->Find(key);
if (pKey != NULL)
{
return pKey->StringVal;
}
}
return "";
}
DEFINE_ACTION_FUNCTION(FLevelLocals, GetUDMFString)
{
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_INT(type);
PARAM_INT(index);
PARAM_NAME(key);
ACTION_RETURN_STRING(GetUDMFString(type, index, key));
}
//=========================================================================== //===========================================================================
// //

View file

@ -225,7 +225,7 @@ static line_t *FindDestination(line_t *src, int tag)
} }
} }
} }
return NULL; return nullptr;
} }
@ -275,7 +275,7 @@ static void SetRotation(FLinePortal *port)
void P_SpawnLinePortal(line_t* line) void P_SpawnLinePortal(line_t* line)
{ {
// portal destination is special argument #0 // portal destination is special argument #0
line_t* dst = NULL; line_t* dst = nullptr;
if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED) if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED)
{ {
@ -304,7 +304,7 @@ void P_SpawnLinePortal(line_t* line)
port->mType = PORTT_TELEPORT; port->mType = PORTT_TELEPORT;
} }
} }
if (port->mDestination != NULL) if (port->mDestination != nullptr)
{ {
port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE; port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE;
} }
@ -357,7 +357,7 @@ void P_SpawnLinePortal(line_t* line)
void P_UpdatePortal(FLinePortal *port) void P_UpdatePortal(FLinePortal *port)
{ {
if (port->mDestination == NULL) if (port->mDestination == nullptr)
{ {
// Portal has no destination: switch it off // Portal has no destination: switch it off
port->mFlags = 0; port->mFlags = 0;
@ -442,16 +442,16 @@ static bool ChangePortalLine(line_t *line, int destid)
if (line->portalindex >= linePortals.Size()) return false; if (line->portalindex >= linePortals.Size()) return false;
FLinePortal *port = &linePortals[line->portalindex]; FLinePortal *port = &linePortals[line->portalindex];
if (port->mType == PORTT_LINKED) return false; // linked portals cannot be changed. if (port->mType == PORTT_LINKED) return false; // linked portals cannot be changed.
if (destid == 0) port->mDestination = NULL; if (destid == 0) port->mDestination = nullptr;
port->mDestination = FindDestination(line, destid); port->mDestination = FindDestination(line, destid);
if (port->mDestination == NULL) if (port->mDestination == nullptr)
{ {
port->mFlags = 0; port->mFlags = 0;
} }
else if (port->mType == PORTT_INTERACTIVE) else if (port->mType == PORTT_INTERACTIVE)
{ {
FLinePortal *portd = &linePortals[port->mDestination->portalindex]; FLinePortal *portd = port->mDestination->portalindex < linePortals.Size()? &linePortals[port->mDestination->portalindex] : nullptr;
if (portd != NULL && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line) if (portd != nullptr && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line)
{ {
// this is a 2-way interactive portal // this is a 2-way interactive portal
port->mFlags = port->mDefFlags | PORTF_INTERACTIVE; port->mFlags = port->mDefFlags | PORTF_INTERACTIVE;
@ -662,7 +662,7 @@ void P_TranslatePortalZ(line_t* src, double& z)
unsigned P_GetSkyboxPortal(AActor *actor) unsigned P_GetSkyboxPortal(AActor *actor)
{ {
if (actor == NULL) return 1; // this means a regular sky. if (actor == nullptr) return 1; // this means a regular sky.
for (unsigned i = 0;i<level.sectorPortals.Size();i++) for (unsigned i = 0;i<level.sectorPortals.Size();i++)
{ {
if (level.sectorPortals[i].mSkybox == actor) return i; if (level.sectorPortals[i].mSkybox == actor) return i;
@ -820,7 +820,7 @@ static bool CollectSectors(int groupid, sector_t *origin)
for (auto line : sec->Lines) for (auto line : sec->Lines)
{ {
sector_t *other = line->frontsector == sec ? line->backsector : line->frontsector; sector_t *other = line->frontsector == sec ? line->backsector : line->frontsector;
if (other != NULL && other != sec && other->PortalGroup != groupid) if (other != nullptr && other != sec && other->PortalGroup != groupid)
{ {
other->PortalGroup = groupid; other->PortalGroup = groupid;
list.Push(other); list.Push(other);
@ -1098,10 +1098,10 @@ void P_CreateLinkedPortals()
} }
// reject would just get in the way when checking sight through portals. // reject would just get in the way when checking sight through portals.
if (Displacements.size > 1 && rejectmatrix != NULL) if (Displacements.size > 1 && rejectmatrix != nullptr)
{ {
delete[] rejectmatrix; delete[] rejectmatrix;
rejectmatrix = NULL; rejectmatrix = nullptr;
} }
// finally we must flag all planes which are obstructed by the sector's own ceiling or floor. // finally we must flag all planes which are obstructed by the sector's own ceiling or floor.
for (auto &sec : level.sectors) for (auto &sec : level.sectors)

View file

@ -91,13 +91,15 @@ size_t s_skipMouseMoves;
void CheckGUICapture() void CheckGUICapture()
{ {
const bool wantCapture = (MENU_Off == menuactive) bool wantCapture = (MENU_Off == menuactive)
? (c_down == ConsoleState || c_falling == ConsoleState || chatmodeon) ? (c_down == ConsoleState || c_falling == ConsoleState || chatmodeon)
: (MENU_On == menuactive || MENU_OnNoPause == menuactive); : (MENU_On == menuactive || MENU_OnNoPause == menuactive);
// [ZZ] check active event handlers that want the UI processing // [ZZ] check active event handlers that want the UI processing
if (!wantCapture && E_CheckUiProcessors()) if (!wantCapture && E_CheckUiProcessors())
{
wantCapture = true; wantCapture = true;
}
if (wantCapture != GUICapture) if (wantCapture != GUICapture)
{ {

View file

@ -284,6 +284,7 @@ void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool
#define CHAN_JUSTSTARTED 512 // internal: Sound has not been updated yet. #define CHAN_JUSTSTARTED 512 // internal: Sound has not been updated yet.
#define CHAN_ABSTIME 1024// internal: Start time is absolute and does not depend on current time. #define CHAN_ABSTIME 1024// internal: Start time is absolute and does not depend on current time.
#define CHAN_VIRTUAL 2048// internal: Channel is currently virtual #define CHAN_VIRTUAL 2048// internal: Channel is currently virtual
#define CHAN_NOSTOP 4096// only for A_PlaySound. Does not start if channel is playing something.
// sound attenuation values // sound attenuation values
#define ATTN_NONE 0.f // full volume the entire level #define ATTN_NONE 0.f // full volume the entire level

View file

@ -840,6 +840,21 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
bool val = sc.CheckNumber() ? !!sc.Number : true; bool val = sc.CheckNumber() ? !!sc.Number : true;
static_cast<PBool*>(f->Type)->SetValue(addr, !!val); static_cast<PBool*>(f->Type)->SetValue(addr, !!val);
} }
else if (f->Type == TypeName)
{
sc.MustGetString();
*(FName*)addr = sc.String;
}
else if (f->Type == TypeSound)
{
sc.MustGetString();
*(FSoundID*)addr = sc.String;
}
else if (f->Type == TypeColor)
{
if (sc.CheckNumber()) *(int*)addr = sc.Number;
else *(PalEntry*)addr = V_GetColor(nullptr, sc);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt))) else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
{ {
sc.MustGetNumber(); sc.MustGetNumber();

View file

@ -1720,7 +1720,19 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
{ {
static_cast<PBool*>(f->Type)->SetValue(addr, !!GetIntConst(ex, ctx)); static_cast<PBool*>(f->Type)->SetValue(addr, !!GetIntConst(ex, ctx));
} }
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt))) else if (f->Type == TypeName)
{
*(FName*)addr = GetStringConst(ex, ctx);
}
else if (f->Type == TypeSound)
{
*(FSoundID*)addr = GetStringConst(ex, ctx);
}
else if (f->Type == TypeColor && ex->ValueType == TypeString) // colors can also be specified as ints.
{
*(PalEntry*)addr = V_GetColor(nullptr, GetStringConst(ex, ctx).GetChars(), &ex->ScriptPosition);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
{ {
static_cast<PInt*>(f->Type)->SetValue(addr, GetIntConst(ex, ctx)); static_cast<PInt*>(f->Type)->SetValue(addr, GetIntConst(ex, ctx));
} }

View file

@ -330,6 +330,11 @@ class Actor : Thinker native
return -1; return -1;
} }
// Called when the player presses 'use' and an actor is found
virtual bool Used(Actor user)
{
return false;
}
native static class<Actor> GetReplacement(class<Actor> cls); native static class<Actor> GetReplacement(class<Actor> cls);
native static class<Actor> GetReplacee(class<Actor> cls); native static class<Actor> GetReplacee(class<Actor> cls);

View file

@ -1,4 +1,4 @@
struct InputEvent native struct InputEventData native
{ {
native uint8 type; native uint8 type;
native uint8 subtype; native uint8 subtype;
@ -418,6 +418,14 @@ class SpotState : Object native
struct LevelLocals native struct LevelLocals native
{ {
enum EUDMF
{
UDMF_Line,
UDMF_Side,
UDMF_Sector,
//UDMF_Thing // not implemented
};
native readonly int time; native readonly int time;
native readonly int maptime; native readonly int maptime;
native readonly int totaltime; native readonly int totaltime;
@ -457,6 +465,11 @@ struct LevelLocals native
native bool frozen; native bool frozen;
native bool infinite_flight; native bool infinite_flight;
// level_info_t *info cannot be done yet. // level_info_t *info cannot be done yet.
native String GetUDMFString(int type, int index, Name key);
native int GetUDMFInt(int type, int index, Name key);
native double GetUDMFFloat(int type, int index, Name key);
} }
struct StringTable native struct StringTable native

View file

@ -413,7 +413,8 @@ enum ESoundFlags
CHAN_MAYBE_LOCAL = 16, CHAN_MAYBE_LOCAL = 16,
CHAN_UI = 32, CHAN_UI = 32,
CHAN_NOPAUSE = 64, CHAN_NOPAUSE = 64,
CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL) CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL),
CHAN_NOSTOP = 4096
}; };

View file

@ -124,7 +124,7 @@ class Lightning : Actor
if ((!thing.player && !thing.bBoss) || !(level.time&1)) if ((!thing.player && !thing.bBoss) || !(level.time&1))
{ {
thing.DamageMobj(self, target, 3, 'Electric'); thing.DamageMobj(self, target, 3, 'Electric');
A_PlaySound(AttackSound, CHAN_WEAPON, 1, true); A_PlaySound(AttackSound, CHAN_WEAPON|CHAN_NOSTOP, 1, false);
if (thing.bIsMonster && random[LightningHit]() < 64) if (thing.bIsMonster && random[LightningHit]() < 64)
{ {
thing.Howl (); thing.Howl ();

View file

@ -84,6 +84,20 @@ struct Side native
native Vertex V2(); native Vertex V2();
native int Index(); native int Index();
int GetUDMFInt(Name nm)
{
return Level.GetUDMFInt(LevelLocals.UDMF_Side, Index(), nm);
}
double GetUDMFFloat(Name nm)
{
return Level.GetUDMFFloat(LevelLocals.UDMF_Side, Index(), nm);
}
String GetUDMFString(Name nm)
{
return Level.GetUDMFString(LevelLocals.UDMF_Side, Index(), nm);
}
}; };
struct Line native struct Line native
@ -142,6 +156,19 @@ struct Line native
native Line getPortalDestination(); native Line getPortalDestination();
native int getPortalAlignment(); native int getPortalAlignment();
native int Index(); native int Index();
int GetUDMFInt(Name nm)
{
return Level.GetUDMFInt(LevelLocals.UDMF_Line, Index(), nm);
}
double GetUDMFFloat(Name nm)
{
return Level.GetUDMFFloat(LevelLocals.UDMF_Line, Index(), nm);
}
String GetUDMFString(Name nm)
{
return Level.GetUDMFString(LevelLocals.UDMF_Line, Index(), nm);
}
} }
struct SecPlane native struct SecPlane native
@ -398,4 +425,18 @@ struct Sector native
{ {
Flags &= ~SECF_SECRET; Flags &= ~SECF_SECRET;
} }
int GetUDMFInt(Name nm)
{
return Level.GetUDMFInt(LevelLocals.UDMF_Sector, Index(), nm);
}
double GetUDMFFloat(Name nm)
{
return Level.GetUDMFFloat(LevelLocals.UDMF_Sector, Index(), nm);
}
String GetUDMFString(Name nm)
{
return Level.GetUDMFString(LevelLocals.UDMF_Sector, Index(), nm);
}
} }

View file

@ -86,7 +86,7 @@ class ListMenu : Menu native
return NULL; return NULL;
} }
//bool Responder (InputEvent ev); //bool Responder (InputEventData ev);
//bool MenuEvent (int mkey, bool fromcontroller); //bool MenuEvent (int mkey, bool fromcontroller);
//bool MouseEvent(int type, int x, int y); //bool MouseEvent(int type, int x, int y);
//void Ticker (); //void Ticker ();

View file

@ -105,7 +105,7 @@ class Menu : Object native
virtual void ReleaseFocus() {} virtual void ReleaseFocus() {}
virtual void ResetColor() {} virtual void ResetColor() {}
native virtual bool Responder(InputEvent ev); native virtual bool Responder(InputEventData ev);
native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MenuEvent (int mkey, bool fromcontroller);
native virtual bool MouseEvent(int type, int mx, int my); native virtual bool MouseEvent(int type, int mx, int my);
native virtual void Ticker(); native virtual void Ticker();

View file

@ -120,17 +120,17 @@ class OptionMenu : Menu
// //
//============================================================================= //=============================================================================
override bool Responder (InputEvent ev) override bool Responder (InputEventData ev)
{ {
if (ev.type == InputEvent.GUI_Event) if (ev.type == InputEventData.GUI_Event)
{ {
if (ev.subtype == InputEvent.GUI_WheelUp) if (ev.subtype == InputEventData.GUI_WheelUp)
{ {
int scrollamt = MIN(2, mDesc.mScrollPos); int scrollamt = MIN(2, mDesc.mScrollPos);
mDesc.mScrollPos -= scrollamt; mDesc.mScrollPos -= scrollamt;
return true; return true;
} }
else if (ev.subtype == InputEvent.GUI_WheelDown) else if (ev.subtype == InputEventData.GUI_WheelDown)
{ {
if (CanScrollDown) if (CanScrollDown)
{ {

View file

@ -396,16 +396,16 @@ class EnterKey : Menu
} }
} }
override bool Responder(InputEvent ev) override bool Responder(InputEventData ev)
{ {
// This checks raw keys, not GUI keys. // This checks raw keys, not GUI keys.
if (ev.type == InputEvent.KeyDown) if (ev.type == InputEventData.KeyDown)
{ {
mOwner.SendKey(ev.data1); mOwner.SendKey(ev.data1);
menuactive = Menu.On; menuactive = Menu.On;
SetMenuMessage(0); SetMenuMessage(0);
Close(); Close();
mParentMenu.MenuEvent((ev.data1 == InputEvent.KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0); mParentMenu.MenuEvent((ev.data1 == InputEventData.KEY_ESCAPE)? Menu.MKEY_Abort : Menu.MKEY_Input, 0);
return true; return true;
} }
return false; return false;

View file

@ -57,9 +57,9 @@ class VideoModeMenu : OptionMenu
return Super.MenuEvent(mkey, fromcontroller); return Super.MenuEvent(mkey, fromcontroller);
} }
override bool Responder(InputEvent ev) override bool Responder(InputEventData ev)
{ {
if (ev.type == InputEvent.GUI_Event && ev.subtype == InputEvent.GUI_KeyDown && (ev.data1 == 0x54 || ev.data1 == 0x74)) if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_KeyDown && (ev.data1 == 0x54 || ev.data1 == 0x74))
{ {
if (SetSelectedSize()) if (SetSelectedSize())
{ {

View file

@ -130,7 +130,7 @@ class PlayerPawn : Actor native
return powerup.EffectTics, maxtics; return powerup.EffectTics, maxtics;
} }
} }
return 0, 0; return -1, -1;
} }
native int GetMaxHealth(); native int GetMaxHealth();