# Conflicts:
#	src/r_things.cpp
This commit is contained in:
nashmuhandes 2016-12-30 12:05:00 +08:00
commit 19d2042364
119 changed files with 1280 additions and 672 deletions

10
game-music-emu/gme/gme_types.h Normal file → Executable file
View file

@ -1,11 +1,13 @@
#ifndef GME_TYPES_H
#define GME_TYPES_H
/*
* This is a default gme_types.h for use when *not* using
* CMake. If CMake is in use gme_types.h.in will be
* processed instead.
/* CMake will either define the following to 1, or #undef it,
* depending on the options passed to CMake. This is used to
* conditionally compile in the various emulator types.
*
* See gme_type_list() in gme.cpp
*/
#define USE_GME_AY
#define USE_GME_GBS
#define USE_GME_GYM

View file

@ -214,14 +214,21 @@ Note: All <bool> fields default to false unless mentioned otherwise.
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
floorterrain = <string>; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.'
ceilingterrain = <string>; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.'
floor_reflect = <float>; // reflectiveness of floor (OpenGL only, not functional on sloped sectors)
ceiling_reflect = <float>; // reflectiveness of ceiling (OpenGL only, not functional on sloped sectors)
floorglowcolor = <integer>; // Sector's floor glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing.
floorglowheight = <float>; // Height of floor glow. This only has an effect for the sector's own glow color, but not for a texture based glow.
ceilingglowcolor = <integer>; // Sector's ceiling glow color as RRGGBB value, default = 'use texture's definition'. Set to -1 to disable glowing.
ceilingglowheight = <float>; // Height of ceiling glow. This only has an effect for the sector's own glow color, but not for a texture based glow.
fogdensity = <integer>; // Sets an explicit fog density for the sector, overriding the default calculation from the light level. Value range is 0-510,
// 0 meaning that the default is to be used, 2 equalling the density of a light level of 250, and 255 equalling the density of
// a light level of 0.
portal_ceil_alpha = <float> // translucency of ceiling portal (default is 0 (not visible))
portal_ceil_blocksound = <bool> // ceiling portal blocks sound.
portal_ceil_disabled = <bool> // ceiling portal disabled.
portal_ceil_nopass = <bool> // ceiling portal blocks movement if true.
portal_ceil_norender = <bool> // ceiling portal not rendered.
portal_ceil_overlaytype = <string> // defines translucency style, can either be "translucent" or "additive". Default is "translucent".
portal_floor_alpha = <float> // translucency of floor portal (default is 0 (not visible))
portal_floor_blocksound = <bool> // floor portal blocks sound.
portal_floor_disabled = <bool> // floor portal disabled.
portal_floor_nopass = <bool> // ceiling portal blocks movement if true.
@ -406,6 +413,9 @@ Added 'moreids' for linedefs and sectors.
added clarification about character encoding
added sector damage properties.
1.27 05.01.2016
floor_reflect and ceiling_reflect.
===============================================================================
EOF
===============================================================================

View file

@ -819,6 +819,7 @@ set (PCH_SOURCES
c_cvars.cpp
c_dispatch.cpp
c_expr.cpp
c_functions.cpp
cmdlib.cpp
colormatcher.cpp
compatibility.cpp
@ -1174,7 +1175,7 @@ source_group("Audio Files\\WildMidi\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRE
source_group("Audio Files\\WildMidi\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/wildmidi/.+\\.cpp$")
source_group("External\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+")
source_group("External\\RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+")
source_group("Externak\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("External\\SFMT" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sfmt/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_strife/.+")
source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+")

View file

@ -34,6 +34,7 @@
// States are tied to finite states are tied to animation frames.
#include "info.h"
#include <forward_list>
#include "doomdef.h"
#include "textures/textures.h"
#include "r_data/renderstyle.h"
@ -562,8 +563,15 @@ inline T *GetDefault ()
struct line_t;
struct secplane_t;
struct msecnode_t;
struct FStrifeDialogueNode;
struct FLinkContext
{
msecnode_t *sector_list = nullptr;
msecnode_t *render_list = nullptr;
};
class DDropItem : public DObject
{
DECLARE_CLASS(DDropItem, DObject)
@ -1036,6 +1044,7 @@ public:
struct sector_t *ceilingsector;
FTextureID ceilingpic; // contacted sec ceilingpic
double radius, Height; // for movement checking
double renderradius;
double projectilepassheight; // height for clipping projectile movement against this actor
@ -1142,6 +1151,8 @@ public:
struct msecnode_t *touching_sectorlist; // phares 3/14/98
struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering
struct portnode_t *render_portallist; // and for cross-lineportal
struct msecnode_t *touching_rendersectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius).
int validcount;
TObjPtr<AInventory> Inventory; // [RH] This actor's inventory
@ -1217,8 +1228,8 @@ private:
bool FixMapthingPos();
public:
void LinkToWorld (bool spawningmapthing=false, sector_t *sector = NULL);
void UnlinkFromWorld ();
void LinkToWorld (FLinkContext *ctx, bool spawningmapthing=false, sector_t *sector = NULL);
void UnlinkFromWorld(FLinkContext *ctx);
void AdjustFloorClip ();
bool InStateSequence(FState * newstate, FState * basestate);
int GetTics(FState * newstate);

View file

@ -118,23 +118,24 @@ void FCajunMaster::Main ()
}
//Check if player should go observer. Or un observe
FLinkContext ctx;
if (bot_observer && !observer && !netgame)
{
Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName());
observer = true;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->UnlinkFromWorld (&ctx);
players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY;
players[consoleplayer].mo->flags2 |= MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
players[consoleplayer].mo->LinkToWorld (&ctx);
}
else if (!bot_observer && observer && !netgame) //Go back
{
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName());
observer = false;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->UnlinkFromWorld (&ctx);
players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY;
players[consoleplayer].mo->flags2 &= ~MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
players[consoleplayer].mo->LinkToWorld (&ctx);
}
}

View file

@ -71,6 +71,7 @@
#include "v_video.h"
#include "r_utility.h"
#include "r_data/r_interpolate.h"
#include "c_functions.h"
extern FILE *Logfile;
extern bool insave;
@ -870,20 +871,17 @@ CCMD (wdir)
//
//
//-----------------------------------------------------------------------------
CCMD(linetarget)
{
FTranslatedLineTarget t;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE, &t, 0.);
C_AimLine(&t, false);
if (t.linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
t.linetarget->GetClass()->TypeName.GetChars(),
t.linetarget->health,
t.linetarget->SpawnHealth());
}
else Printf("No target found\n");
C_PrintInfo(t.linetarget);
else
Printf("No target found\n");
}
// As linetarget, but also give info about non-shootable actors
@ -892,28 +890,18 @@ CCMD(info)
FTranslatedLineTarget t;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE,
&t, 0., ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART);
C_AimLine(&t, true);
if (t.linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
t.linetarget->GetClass()->TypeName.GetChars(),
t.linetarget->health,
t.linetarget->SpawnHealth());
PrintMiscActorInfo(t.linetarget);
}
else Printf("No target found. Info cannot find actors that have "
C_PrintInfo(t.linetarget);
else
Printf("No target found. Info cannot find actors that have "
"the NOBLOCKMAP flag or have height/radius of 0.\n");
}
CCMD(myinfo)
{
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
players[consoleplayer].mo->GetClass()->TypeName.GetChars(),
players[consoleplayer].mo->health,
players[consoleplayer].mo->SpawnHealth());
PrintMiscActorInfo(players[consoleplayer].mo);
C_PrintInfo(players[consoleplayer].mo);
}
typedef bool (*ActorTypeChecker) (AActor *);

View file

@ -1573,7 +1573,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
static TArray<char> command;
const size_t length = buffer.Text.Len();
command.Resize(length + 1);
command.Resize(unsigned(length + 1));
memcpy(&command[0], buffer.Text.GetChars(), length);
command[length] = '\0';

84
src/c_functions.cpp Normal file
View file

@ -0,0 +1,84 @@
/*
** c_functions.cpp
** Miscellaneous console command helper functions.
**
**---------------------------------------------------------------------------
** Copyright 2016 Rachael Alexanderson
** Copyright 2003-2016 Christoph Oelckers
** Copyright 1998-2016 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "d_player.h"
#include "p_local.h"
#include "c_functions.h"
void C_PrintInfo(AActor *target)
{
if (target->player)
Printf("Player=%s, ", target->player->userinfo.GetName());
Printf("Class=%s, Health=%d, Spawnhealth=%d\n",
target->GetClass()->TypeName.GetChars(),
target->health,
target->SpawnHealth());
PrintMiscActorInfo(target);
}
void C_AimLine(FTranslatedLineTarget *t, bool nonshootable)
{
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE, t, 0.,
(nonshootable) ? ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART : 0);
}
void C_PrintInv(AActor *target)
{
AInventory *item;
int count = 0;
if (target == NULL)
{
Printf("No target found!\n");
return;
}
if (target->player)
Printf("Inventory for Player '%s':\n", target->player->userinfo.GetName());
else
Printf("Inventory for Target '%s':\n", target->GetClass()->TypeName.GetChars());
for (item = target->Inventory; item != NULL; item = item->Inventory)
{
Printf (" %s #%u (%d/%d)\n", item->GetClass()->TypeName.GetChars(),
item->InventoryID,
item->Amount, item->MaxAmount);
count++;
}
Printf (" List count: %d\n", count);
}

39
src/c_functions.h Normal file
View file

@ -0,0 +1,39 @@
/*
** c_functions.h
** Miscellaneous console command helper functions.
**
**---------------------------------------------------------------------------
** Copyright 2016 Rachael Alexanderson
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
void C_PrintInv(AActor *target);
void C_AimLine(FTranslatedLineTarget *t, bool nonshootable);
void C_PrintInfo(AActor *target);
struct FTranslatedLineTarget;

View file

@ -533,8 +533,9 @@ void SetCompatibilityParams()
if (CompatParams[i+1] < numsectors)
{
sector_t *sec = &sectors[CompatParams[i+1]];
sec->floorplane.ChangeHeight(CompatParams[i+2]);
sec->ChangePlaneTexZ(sector_t::floor, CompatParams[i+2] / 65536.);
const double delta = CompatParams[i + 2] / 65536.0;
sec->floorplane.ChangeHeight(delta);
sec->ChangePlaneTexZ(sector_t::floor, delta);
}
i += 3;
break;

View file

@ -643,15 +643,21 @@ bool FConfigFile::ReadConfig (void *file)
{
continue;
}
// Remove white space at end of line
endpt = start + strlen (start) - 1;
while (endpt > start && *endpt <= ' ')
// Do not process tail of long line
const bool longline = 255 == strlen(readbuf) && '\n' != readbuf[254];
if (!longline)
{
endpt--;
// Remove white space at end of line
endpt = start + strlen (start) - 1;
while (endpt > start && *endpt <= ' ')
{
endpt--;
}
// Remove line feed '\n' character
endpt[1] = 0;
if (endpt <= start)
continue; // Nothing here
}
endpt[1] = 0;
if (endpt <= start)
continue; // Nothing here
if (*start == '[')
{ // Section header
@ -687,6 +693,31 @@ bool FConfigFile::ReadConfig (void *file)
{
ReadMultiLineValue (file, section, start, whiteprobe + 3);
}
else if (longline)
{
const FString key = start;
FString value = whiteprobe;
while (ReadLine (readbuf, READBUFFERSIZE, file) != NULL)
{
const size_t endpos = (0 == readbuf[0]) ? 0 : (strlen(readbuf) - 1);
const bool endofline = '\n' == readbuf[endpos];
if (endofline)
{
readbuf[endpos] = 0;
}
value += readbuf;
if (endofline)
{
break;
}
}
NewConfigEntry (section, key.GetChars(), value.GetChars());
}
else
{
NewConfigEntry (section, start, whiteprobe);

View file

@ -552,3 +552,9 @@ void DObject::CheckIfSerialized () const
}
}
DEFINE_ACTION_FUNCTION(DObject, GetClassName)
{
PARAM_SELF_PROLOGUE(DObject);
ACTION_RETURN_INT(self->GetClass()->TypeName);
}

View file

@ -135,17 +135,17 @@ DMovingCeiling::DMovingCeiling (sector_t *sector, bool interpolate)
if (interpolate) interpolation = sector->SetInterpolation(sector_t::CeilingMove, true);
}
bool sector_t::MoveAttached(int crush, double move, int floorOrCeiling, bool resetfailed)
bool sector_t::MoveAttached(int crush, double move, int floorOrCeiling, bool resetfailed, bool instant)
{
if (!P_Scroll3dMidtex(this, crush, move, !!floorOrCeiling) && resetfailed)
if (!P_Scroll3dMidtex(this, crush, move, !!floorOrCeiling, instant) && resetfailed)
{
P_Scroll3dMidtex(this, crush, -move, !!floorOrCeiling);
P_Scroll3dMidtex(this, crush, -move, !!floorOrCeiling, instant);
return false;
}
if (!P_MoveLinkedSectors(this, crush, move, !!floorOrCeiling) && resetfailed)
if (!P_MoveLinkedSectors(this, crush, move, !!floorOrCeiling, instant) && resetfailed)
{
P_MoveLinkedSectors(this, crush, -move, !!floorOrCeiling);
P_Scroll3dMidtex(this, crush, -move, !!floorOrCeiling);
P_MoveLinkedSectors(this, crush, -move, !!floorOrCeiling, instant);
P_Scroll3dMidtex(this, crush, -move, !!floorOrCeiling, instant);
return false;
}
return true;
@ -157,7 +157,7 @@ bool sector_t::MoveAttached(int crush, double move, int floorOrCeiling, bool res
// (Use -1 to prevent it from trying to crush)
// dest is the desired d value for the plane
//
EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush)
EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush, bool instant)
{
bool flag;
double lastpos;
@ -175,15 +175,15 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct
{
move = floorplane.HeightDiff(lastpos, dest);
if (!MoveAttached(crush, move, 0, true)) return EMoveResult::crushed;
if (!MoveAttached(crush, move, 0, true, instant)) return EMoveResult::crushed;
floorplane.setD(dest);
flag = P_ChangeSector(this, crush, move, 0, false);
flag = P_ChangeSector(this, crush, move, 0, false, instant);
if (flag)
{
floorplane.setD(lastpos);
P_ChangeSector(this, crush, -move, 0, true);
MoveAttached(crush, -move, 0, false);
P_ChangeSector(this, crush, -move, 0, true, instant);
MoveAttached(crush, -move, 0, false, instant);
}
else
{
@ -194,16 +194,16 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct
}
else
{
if (!MoveAttached(crush, -speed, 0, true)) return EMoveResult::crushed;
if (!MoveAttached(crush, -speed, 0, true, instant)) return EMoveResult::crushed;
floorplane.setD(movedest);
flag = P_ChangeSector(this, crush, -speed, 0, false);
flag = P_ChangeSector(this, crush, -speed, 0, false, instant);
if (flag)
{
floorplane.setD(lastpos);
P_ChangeSector(this, crush, speed, 0, true);
MoveAttached(crush, speed, 0, false);
P_ChangeSector(this, crush, speed, 0, true, instant);
MoveAttached(crush, speed, 0, false, instant);
return EMoveResult::crushed;
}
else
@ -232,16 +232,16 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct
{
move = floorplane.HeightDiff(lastpos, dest);
if (!MoveAttached(crush, move, 0, true)) return EMoveResult::crushed;
if (!MoveAttached(crush, move, 0, true, instant)) return EMoveResult::crushed;
floorplane.setD(dest);
flag = P_ChangeSector(this, crush, move, 0, false);
flag = P_ChangeSector(this, crush, move, 0, false, instant);
if (flag)
{
floorplane.setD(lastpos);
P_ChangeSector(this, crush, -move, 0, true);
MoveAttached(crush, -move, 0, false);
P_ChangeSector(this, crush, -move, 0, true, instant);
MoveAttached(crush, -move, 0, false, instant);
}
else
{
@ -252,12 +252,12 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct
}
else
{
if (!MoveAttached(crush, speed, 0, true)) return EMoveResult::crushed;
if (!MoveAttached(crush, speed, 0, true, instant)) return EMoveResult::crushed;
floorplane.setD(movedest);
// COULD GET CRUSHED
flag = P_ChangeSector(this, crush, speed, 0, false);
flag = P_ChangeSector(this, crush, speed, 0, false, instant);
if (flag)
{
if (crush >= 0 && !hexencrush)
@ -267,8 +267,8 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct
return EMoveResult::crushed;
}
floorplane.setD(lastpos);
P_ChangeSector(this, crush, -speed, 0, true);
MoveAttached(crush, -speed, 0, false);
P_ChangeSector(this, crush, -speed, 0, true, instant);
MoveAttached(crush, -speed, 0, false, instant);
return EMoveResult::crushed;
}
ChangePlaneTexZ(sector_t::floor, floorplane.HeightDiff(lastpos));

View file

@ -2677,13 +2677,13 @@ void FParser::SF_PlayerWeapon()
if (playernum==-1) return;
if (weaponnum<0 || weaponnum>9)
{
script_error("weaponnum out of range! %s\n", weaponnum);
script_error("weaponnum out of range! %d\n", weaponnum);
return;
}
PClassWeapon * ti = static_cast<PClassWeapon *>(PClass::FindActor(WeaponNames[weaponnum]));
if (!ti)
{
script_error("incompatibility in playerweapon\n", weaponnum);
script_error("incompatibility in playerweapon %d\n", weaponnum);
return;
}
@ -2758,13 +2758,13 @@ void FParser::SF_PlayerSelectedWeapon()
if (weaponnum<0 || weaponnum>=9)
{
script_error("weaponnum out of range! %s\n", weaponnum);
script_error("weaponnum out of range! %d\n", weaponnum);
return;
}
PClassWeapon * ti = static_cast<PClassWeapon *>(PClass::FindActor(WeaponNames[weaponnum]));
if (!ti)
{
script_error("incompatibility in playerweapon\n", weaponnum);
script_error("incompatibility in playerweapon %d\n", weaponnum);
return;
}

View file

@ -246,7 +246,7 @@ void FMapInfoParser::ParseDoomEdNums()
}
if (error > 0)
{
sc.ScriptError("%d errors encountered in DoomEdNum definition");
sc.ScriptError("%d errors encountered in DoomEdNum definition", error);
}
}

View file

@ -1893,7 +1893,7 @@ void APowerMorph::InitEffect( )
if (Owner != nullptr && Owner->player != nullptr && PlayerClass != nullptr)
{
player_t *realplayer = Owner->player; // Remember the identity of the player
if (P_MorphPlayer(realplayer, realplayer, PlayerClass, -1/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
if (P_MorphPlayer(realplayer, realplayer, PlayerClass, INT_MAX/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
{
Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor)

View file

@ -21,6 +21,7 @@
#include "serializer.h"
#include "virtual.h"
#include "a_ammo.h"
#include "c_functions.h"
EXTERN_CVAR(Bool, sv_unlimited_pickup)
@ -636,14 +637,9 @@ void AInventory::BecomeItem ()
{
if (!(flags & (MF_NOBLOCKMAP|MF_NOSECTOR)))
{
UnlinkFromWorld ();
if (sector_list)
{
P_DelSeclist (sector_list);
sector_list = NULL;
}
UnlinkFromWorld (nullptr);
flags |= MF_NOBLOCKMAP|MF_NOSECTOR;
LinkToWorld ();
LinkToWorld (nullptr);
}
RemoveFromHash ();
flags &= ~MF_SPECIAL;
@ -674,9 +670,9 @@ void AInventory::BecomePickup ()
}
if (flags & (MF_NOBLOCKMAP|MF_NOSECTOR))
{
UnlinkFromWorld ();
UnlinkFromWorld (nullptr);
flags &= ~(MF_NOBLOCKMAP|MF_NOSECTOR);
LinkToWorld ();
LinkToWorld (nullptr);
P_FindFloorCeiling (this);
}
flags = (GetDefault()->flags | MF_DROPPED) & ~MF_COUNTITEM;
@ -1572,7 +1568,6 @@ bool AInventory::CanPickup (AActor *toucher)
CCMD (printinv)
{
AInventory *item;
int pnum = consoleplayer;
#ifdef _DEBUG
@ -1586,37 +1581,21 @@ CCMD (printinv)
}
}
#endif
if (players[pnum].mo == NULL)
{
return;
}
for (item = players[pnum].mo->Inventory; item != NULL; item = item->Inventory)
{
Printf ("%s #%u (%d/%d)\n", item->GetClass()->TypeName.GetChars(),
item->InventoryID,
item->Amount, item->MaxAmount);
}
C_PrintInv(players[pnum].mo);
}
CCMD (targetinv)
{
AInventory *item;
FTranslatedLineTarget t;
if (CheckCheatmode () || players[consoleplayer].mo == NULL)
return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->Angles.Yaw, MISSILERANGE,
&t, 0., ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART);
C_AimLine(&t, true);
if (t.linetarget)
{
for (item = t.linetarget->Inventory; item != NULL; item = item->Inventory)
{
Printf ("%s #%u (%d/%d)\n", item->GetClass()->TypeName.GetChars(),
item->InventoryID,
item->Amount, item->MaxAmount);
}
C_PrintInv(t.linetarget);
}
else Printf("No target found. Targetinv cannot find actors that have "
"the NOBLOCKMAP flag or have height/radius of 0.\n");

View file

@ -653,7 +653,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill
if (thiscluster && (thiscluster->flags & CLUSTER_HUB))
{
if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster))
if ((level.flags & LEVEL_NOINTERMISSION) || ((nextcluster == thiscluster) && !(thiscluster->flags & CLUSTER_ALLOWINTERMISSION)))
NoWipe = 35;
D_DrawIcon = "TELEICON";
}
@ -874,7 +874,7 @@ void G_DoCompleted (void)
if (!deathmatch &&
((level.flags & LEVEL_NOINTERMISSION) ||
((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB))))
((nextcluster == thiscluster) && (thiscluster->flags & CLUSTER_HUB) && !(thiscluster->flags & CLUSTER_ALLOWINTERMISSION))))
{
G_WorldDone ();
return;
@ -1196,8 +1196,7 @@ void G_StartTravel ()
// Only living players travel. Dead ones get a new body on the new level.
if (players[i].health > 0)
{
pawn->UnlinkFromWorld ();
P_DelSector_List ();
pawn->UnlinkFromWorld (nullptr);
int tid = pawn->tid; // Save TID
pawn->RemoveFromHash ();
pawn->tid = tid; // Restore TID (but no longer linked into the hash chain)
@ -1206,8 +1205,7 @@ void G_StartTravel ()
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
{
inv->ChangeStatNum (STAT_TRAVELLING);
inv->UnlinkFromWorld ();
P_DelSector_List ();
inv->UnlinkFromWorld (nullptr);
}
}
}
@ -1304,7 +1302,7 @@ void G_FinishTravel ()
{
pawndup->Destroy();
}
pawn->LinkToWorld ();
pawn->LinkToWorld (nullptr);
pawn->ClearInterpolation();
pawn->AddToHash ();
pawn->SetState(pawn->SpawnState);
@ -1313,7 +1311,7 @@ void G_FinishTravel ()
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
{
inv->ChangeStatNum (STAT_INVENTORY);
inv->LinkToWorld ();
inv->LinkToWorld (nullptr);
inv->Travelled ();
}
if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED)
@ -1570,7 +1568,7 @@ void G_UnSnapshotLevel (bool hubLoad)
// If this isn't the unmorphed original copy of a player, destroy it, because it's extra.
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].morphTics && players[i].mo->tracer == pawn)
if (playeringame[i] && players[i].morphTics && players[i].mo->alternative == pawn)
{
break;
}

View file

@ -473,6 +473,7 @@ struct cluster_info_t
#define CLUSTER_LOOKUPENTERTEXT 0x00000020 // Enter text is the name of a language string
#define CLUSTER_LOOKUPNAME 0x00000040 // Name is the name of a language string
#define CLUSTER_LOOKUPCLUSTERNAME 0x00000080 // Cluster name is the name of a language string
#define CLUSTER_ALLOWINTERMISSION 0x00000100 // Allow intermissions between levels in a hub.
extern FLevelLocals level;

View file

@ -699,6 +699,10 @@ void FMapInfoParser::ParseCluster()
{
clusterinfo->flags |= CLUSTER_HUB;
}
else if (sc.Compare("allowintermission"))
{
clusterinfo->flags |= CLUSTER_ALLOWINTERMISSION;
}
else if (sc.Compare("cdtrack"))
{
ParseAssign();

View file

@ -12,6 +12,7 @@
#include <zlib.h>
#include <new>
#include <algorithm>
#include <forward_list>
#include <sys/stat.h>
#include <sys/types.h>
#include <cassert>

View file

@ -364,6 +364,7 @@ void APathFollower::NewNode ()
bool APathFollower::Interpolate ()
{
DVector3 dpos(0, 0, 0);
FLinkContext ctx;
if ((args[2] & 8) && Time > 0.f)
{
@ -372,7 +373,7 @@ bool APathFollower::Interpolate ()
if (CurrNode->Next==NULL) return false;
UnlinkFromWorld ();
UnlinkFromWorld (&ctx);
DVector3 newpos;
if (args[2] & 1)
{ // linear
@ -389,7 +390,7 @@ bool APathFollower::Interpolate ()
newpos.Z = Splerp(PrevNode->Z(), CurrNode->Z(), CurrNode->Next->Z(), CurrNode->Next->Next->Z());
}
SetXYZ(newpos);
LinkToWorld ();
LinkToWorld (&ctx);
if (args[2] & 6)
{
@ -541,10 +542,11 @@ void AActorMover::Activate (AActor *activator)
tracer->flags |= MF_NOGRAVITY;
if (args[2] & 128)
{
tracer->UnlinkFromWorld ();
FLinkContext ctx;
tracer->UnlinkFromWorld (&ctx);
tracer->flags |= MF_NOBLOCKMAP;
tracer->flags &= ~MF_SOLID;
tracer->LinkToWorld ();
tracer->LinkToWorld (&ctx);
}
if (tracer->flags3 & MF3_ISMONSTER)
{
@ -563,9 +565,10 @@ void AActorMover::Deactivate (AActor *activator)
Super::Deactivate (activator);
if (tracer != NULL)
{
tracer->UnlinkFromWorld ();
FLinkContext ctx;
tracer->UnlinkFromWorld (&ctx);
tracer->flags = ActorFlags::FromInt (special1);
tracer->LinkToWorld ();
tracer->LinkToWorld (&ctx);
tracer->flags2 = ActorFlags2::FromInt (special2);
}
}

View file

@ -515,7 +515,7 @@ void GLWall::RenderFogBoundaryCompat()
{
// without shaders some approximation is needed. This won't look as good
// as the shader version but it's an acceptable compromise.
float fogdensity = gl_GetFogDensity(lightlevel, Colormap.FadeColor);
float fogdensity = gl_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.fogdensity);
float dist1 = Dist2(ViewPos.X, ViewPos.Y, glseg.x1, glseg.y1);
float dist2 = Dist2(ViewPos.X, ViewPos.Y, glseg.x2, glseg.y2);

View file

@ -236,7 +236,7 @@ void ADynamicLight::Activate(AActor *activator)
m_cycler.SetParams(float(m_Radius[1]), float(m_Radius[0]), pulseTime);
m_cycler.ShouldCycle(true);
m_cycler.SetCycleType(CYCLE_Sin);
m_currentRadius = (BYTE)m_cycler.GetVal();
m_currentRadius = m_cycler.GetVal();
}
}
@ -599,7 +599,6 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
for (unsigned i = 0; i < collected_ss.Size(); i++)
{
subSec = collected_ss[i].sub;
auto &pos = collected_ss[i].pos;
touching_subsectors = AddLightNode(&subSec->lighthead, subSec, this, touching_subsectors);
if (subSec->sector->validcount != ::validcount)
@ -608,9 +607,10 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
subSec->sector->validcount = ::validcount;
}
for (unsigned int i = 0; i < subSec->numlines; i++)
for (unsigned int j = 0; j < subSec->numlines; ++j)
{
seg_t * seg = subSec->firstline + i;
auto &pos = collected_ss[i].pos;
seg_t *seg = subSec->firstline + j;
// check distance from x/y to seg and if within radius add this seg and, if present the opposing subsector (lather/rinse/repeat)
// If out of range we do not need to bother with this seg.

View file

@ -167,6 +167,8 @@ FLightDefaults::FLightDefaults(FName name, ELightType type)
void FLightDefaults::ApplyProperties(ADynamicLight * light) const
{
auto oldtype = light->lighttype;
light->lighttype = m_type;
light->specialf1 = m_Param;
light->SetOffset(m_Pos);
@ -179,6 +181,17 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
if (m_additive) light->flags4 |= MF4_ADDITIVE;
if (m_dontlightself) light->flags4 |= MF4_DONTLIGHTSELF;
light->m_tickCount = 0;
if (m_type == PulseLight)
{
float pulseTime = float(m_Param / TICRATE);
light->m_lastUpdate = level.maptime;
light->m_cycler.SetParams(float(light->m_Radius[1]), float(light->m_Radius[0]), pulseTime, oldtype == PulseLight);
light->m_cycler.ShouldCycle(true);
light->m_cycler.SetCycleType(CYCLE_Sin);
light->m_currentRadius = light->m_cycler.GetVal();
}
switch (m_attenuate)
{
case 0: light->flags4 &= ~MF4_ATTENUATE; break;

View file

@ -33,7 +33,7 @@ EXTERN_CVAR(Bool, gl_attachedlights)
class ADynamicLight;
class FSerializer;
class FLightDefaults;
enum
@ -91,6 +91,7 @@ struct FLightNode
class ADynamicLight : public AActor
{
friend class FLightDefaults;
DECLARE_CLASS (ADynamicLight, AActor)
public:
virtual void Tick();

View file

@ -52,7 +52,7 @@ void gl_InitGlow(FScanner &sc)
sc.MustGetString();
FTextureID flump=TexMan.CheckForTexture(sc.String, FTexture::TEX_Flat,FTextureManager::TEXMAN_TryAny);
FTexture *tex = TexMan[flump];
if (tex) tex->gl_info.bGlowing = tex->gl_info.bFullbright = true;
if (tex) tex->gl_info.bAutoGlowing = tex->gl_info.bGlowing = tex->gl_info.bFullbright = true;
}
}
else if (sc.Compare("WALLS"))
@ -63,7 +63,7 @@ void gl_InitGlow(FScanner &sc)
sc.MustGetString();
FTextureID flump=TexMan.CheckForTexture(sc.String, FTexture::TEX_Wall,FTextureManager::TEXMAN_TryAny);
FTexture *tex = TexMan[flump];
if (tex) tex->gl_info.bGlowing = tex->gl_info.bFullbright = true;
if (tex) tex->gl_info.bAutoGlowing = tex->gl_info.bGlowing = tex->gl_info.bFullbright = true;
}
}
else if (sc.Compare("TEXTURE"))
@ -93,6 +93,7 @@ void gl_InitGlow(FScanner &sc)
if (tex && color != 0)
{
tex->gl_info.bAutoGlowing = false;
tex->gl_info.bGlowing = true;
tex->gl_info.GlowColor = color;
}
@ -106,17 +107,39 @@ void gl_InitGlow(FScanner &sc)
// Checks whether a sprite should be affected by a glow
//
//==========================================================================
int gl_CheckSpriteGlow(sector_t *sec, int lightlevel, const DVector3 &pos)
int gl_CheckSpriteGlow(sector_t *sector, int lightlevel, const DVector3 &pos)
{
FTextureID floorpic = sec->GetTexture(sector_t::floor);
FTexture *tex = TexMan[floorpic];
if (tex != NULL && tex->isGlowing())
float bottomglowcolor[4];
bottomglowcolor[3] = 0;
auto c = sector->planes[sector_t::floor].GlowColor;
if (c == 0)
{
double floordiff = pos.Z - sec->floorplane.ZatPoint(pos);
if (floordiff < tex->gl_info.GlowHeight && tex->gl_info.GlowHeight != 0)
FTexture *tex = TexMan[sector->GetTexture(sector_t::floor)];
if (tex != NULL && tex->isGlowing())
{
if (!tex->gl_info.bAutoGlowing) tex = TexMan(sector->GetTexture(sector_t::floor));
if (tex->isGlowing()) // recheck the current animation frame.
{
tex->GetGlowColor(bottomglowcolor);
bottomglowcolor[3] = (float)tex->gl_info.GlowHeight;
}
}
}
else if (c != -1)
{
bottomglowcolor[0] = c.r / 255.f;
bottomglowcolor[1] = c.g / 255.f;
bottomglowcolor[2] = c.b / 255.f;
bottomglowcolor[3] = sector->planes[sector_t::floor].GlowHeight;
}
if (bottomglowcolor[3]> 0)
{
double floordiff = pos.Z - sector->floorplane.ZatPoint(pos);
if (floordiff < bottomglowcolor[3])
{
int maxlight = (255 + lightlevel) >> 1;
double lightfrac = floordiff / tex->gl_info.GlowHeight;
double lightfrac = floordiff / bottomglowcolor[3];
if (lightfrac < 0) lightfrac = 0;
lightlevel = int(lightfrac*lightlevel + maxlight*(1 - lightfrac));
}
@ -124,3 +147,71 @@ int gl_CheckSpriteGlow(sector_t *sec, int lightlevel, const DVector3 &pos)
return lightlevel;
}
//==========================================================================
//
// Checks whether a wall should glow
//
//==========================================================================
bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolor)
{
bool ret = false;
bottomglowcolor[3] = topglowcolor[3] = 0;
auto c = sector->planes[sector_t::ceiling].GlowColor;
if (c == 0)
{
FTexture *tex = TexMan[sector->GetTexture(sector_t::ceiling)];
if (tex != NULL && tex->isGlowing())
{
if (!tex->gl_info.bAutoGlowing) tex = TexMan(sector->GetTexture(sector_t::ceiling));
if (tex->isGlowing()) // recheck the current animation frame.
{
ret = true;
tex->GetGlowColor(topglowcolor);
topglowcolor[3] = (float)tex->gl_info.GlowHeight;
}
}
}
else if (c != -1)
{
topglowcolor[0] = c.r / 255.f;
topglowcolor[1] = c.g / 255.f;
topglowcolor[2] = c.b / 255.f;
topglowcolor[3] = sector->planes[sector_t::ceiling].GlowHeight;
ret = topglowcolor[3] > 0;
}
c = sector->planes[sector_t::floor].GlowColor;
if (c == 0)
{
FTexture *tex = TexMan[sector->GetTexture(sector_t::floor)];
if (tex != NULL && tex->isGlowing())
{
if (!tex->gl_info.bAutoGlowing) tex = TexMan(sector->GetTexture(sector_t::floor));
if (tex->isGlowing()) // recheck the current animation frame.
{
ret = true;
tex->GetGlowColor(bottomglowcolor);
bottomglowcolor[3] = (float)tex->gl_info.GlowHeight;
}
}
}
else if (c != -1)
{
bottomglowcolor[0] = c.r / 255.f;
bottomglowcolor[1] = c.g / 255.f;
bottomglowcolor[2] = c.b / 255.f;
bottomglowcolor[3] = sector->planes[sector_t::floor].GlowHeight;
ret = bottomglowcolor[3] > 0;
}
return ret;
}
#include "c_dispatch.h"
#include "d_player.h"
CCMD(setglow)
{
auto s = players[0].mo->Sector;
s->planes[sector_t::floor].GlowHeight = 128;
s->planes[sector_t::floor].GlowColor = 0xff0000;
}

View file

@ -6,5 +6,6 @@ struct sector_t;
void gl_InitGlow(const char * lumpnm);
int gl_CheckSpriteGlow(sector_t *sec, int lightlevel, const DVector3 &pos);
bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolor);
#endif

View file

@ -32,6 +32,7 @@ struct FColormap
PalEntry FadeColor; // a is fadedensity>>1
int desaturation;
int blendfactor;
int fogdensity;
void Clear()
{
@ -39,6 +40,7 @@ struct FColormap
FadeColor=0;
desaturation = 0;
blendfactor=0;
fogdensity = 0;
}
void ClearColor()
@ -55,6 +57,7 @@ struct FColormap
desaturation = from->Desaturate;
FadeColor = from->Fade;
blendfactor = from->Color.a;
fogdensity = from->Fade.a*2;
return * this;
}

View file

@ -196,14 +196,30 @@ int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon)
if ((glset.lightmode & 2) && lightlevel < 192 && !weapon)
{
light = xs_CRoundToInt(192.f - (192-lightlevel)* 1.95f);
if (lightlevel > 100)
{
light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f);
if (light + rellight < 20)
{
light = 20 + (light + rellight - 20) / 5;
}
else
{
light += rellight;
}
}
else
{
light = (lightlevel + rellight) / 5;
}
}
else
{
light=lightlevel;
light=lightlevel+rellight;
}
return clamp(light+rellight, 0, 255);
return clamp(light, 0, 255);
}
//==========================================================================
@ -278,43 +294,48 @@ void gl_SetColor(int sectorlightlevel, int rellight, const FColormap &cm, float
//
//==========================================================================
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor)
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
{
float density;
if (glset.lightmode&4)
if (glset.lightmode & 4)
{
// uses approximations of Legacy's default settings.
density = fogdensity? fogdensity : 18;
density = fogdensity ? fogdensity : 18;
}
else if ((fogcolor.d & 0xffffff) == 0)
{
// case 1: black fog
if (glset.lightmode != 8)
{
density=distfogtable[glset.lightmode!=0][gl_ClampLight(lightlevel)];
density = distfogtable[glset.lightmode != 0][gl_ClampLight(lightlevel)];
}
else
{
density = 0;
}
}
else if (outsidefogdensity != 0 && outsidefogcolor.a!=0xff && (fogcolor.d & 0xffffff) == (outsidefogcolor.d & 0xffffff))
else if (sectorfogdensity != 0)
{
// case 2. outsidefogdensity has already been set as needed
density=outsidefogdensity;
// case 2: Sector has an explicit fog density set.
density = sectorfogdensity;
}
else if (fogdensity!=0)
else if (outsidefogdensity != 0 && outsidefogcolor.a != 0xff && (fogcolor.d & 0xffffff) == (outsidefogcolor.d & 0xffffff))
{
// case 3: level has fog density set
density=fogdensity;
// case 3. outsidefogdensity has already been set as needed
density = outsidefogdensity;
}
else if (fogdensity != 0)
{
// case 4: level has fog density set
density = fogdensity;
}
else if (lightlevel < 248)
{
// case 4: use light level
density=clamp<int>(255-lightlevel,30,255);
// case 5: use light level
density = clamp<int>(255 - lightlevel, 30, 255);
}
else
else
{
density = 0.f;
}
@ -471,7 +492,7 @@ void gl_SetFog(int lightlevel, int rellight, const FColormap *cmap, bool isaddit
else if (cmap != NULL && gl_fixedcolormap == 0)
{
fogcolor = cmap->FadeColor;
fogdensity = gl_GetFogDensity(lightlevel, fogcolor);
fogdensity = gl_GetFogDensity(lightlevel, fogcolor, cmap->fogdensity);
fogcolor.a=0;
}
else

View file

@ -18,7 +18,7 @@ void gl_SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefog
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon);
void gl_SetColor(int light, int rellight, const FColormap &cm, float alpha, bool weapon=false);
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor);
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity);
struct sector_t;
bool gl_CheckFog(FColormap *cm, int lightlevel);
bool gl_CheckFog(sector_t *frontsector, sector_t *backsector);

View file

@ -72,7 +72,7 @@
EXTERN_CVAR(Int, screenblocks)
CVAR(Bool, gl_scale_viewport, true, 0);
CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE);
//===========================================================================
//
@ -286,7 +286,7 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds)
mSceneViewport.height = height;
// Scale viewports to fit letterbox
if (gl_scale_viewport || !FGLRenderBuffers::IsEnabled())
if ((gl_scale_viewport && !framebuffer->IsFullscreen()) || !FGLRenderBuffers::IsEnabled())
{
mScreenViewport.width = mOutputLetterbox.width;
mScreenViewport.height = mOutputLetterbox.height;

View file

@ -363,8 +363,12 @@ static inline void RenderThings(subsector_t * sub, sector_t * sector)
SetupSprite.Clock();
sector_t * sec=sub->sector;
// Handle all things in sector.
for (AActor * thing = sec->thinglist; thing; thing = thing->snext)
for (auto p = sec->touching_renderthings; p != nullptr; p = p->m_snext)
{
auto thing = p->m_thing;
if (thing->validcount == validcount) continue;
thing->validcount = validcount;
FIntCVar *cvar = thing->GetClass()->distancecheck;
if (cvar != NULL && *cvar >= 0)
{
@ -378,6 +382,7 @@ static inline void RenderThings(subsector_t * sub, sector_t * sector)
GLRenderer->ProcessSprite(thing, sector, false);
}
for (msecnode_t *node = sec->render_thinglist; node; node = node->m_snext)
{
AActor *thing = node->m_thing;

View file

@ -283,11 +283,11 @@ bool GLPortal::Start(bool usestencil, bool doquery)
// save viewpoint
savedViewPos = ViewPos;
savedViewActorPos = ViewActorPos;
savedshowviewer = r_showviewer;
savedAngle = ViewAngle;
savedviewactor=GLRenderer->mViewActor;
savedviewarea=in_area;
savedviewpath[0] = ViewPath[0];
savedviewpath[1] = ViewPath[1];
savedvisibility = camera ? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0);
@ -350,9 +350,9 @@ void GLPortal::End(bool usestencil)
if (needdepth) FDrawInfo::EndDrawInfo();
// Restore the old view
ViewPath[0] = savedviewpath[0];
ViewPath[1] = savedviewpath[1];
ViewPos = savedViewPos;
r_showviewer = savedshowviewer;
ViewActorPos = savedViewActorPos;
ViewAngle = savedAngle;
GLRenderer->mViewActor=savedviewactor;
in_area=savedviewarea;
@ -409,6 +409,8 @@ void GLPortal::End(bool usestencil)
glDepthMask(true);
}
// Restore the old view
r_showviewer = savedshowviewer;
ViewActorPos = savedViewActorPos;
ViewPos = savedViewPos;
ViewAngle = savedAngle;
GLRenderer->mViewActor=savedviewactor;
@ -628,6 +630,7 @@ void GLSkyboxPortal::DrawContents()
bool oldclamp = gl_RenderState.SetDepthClamp(false);
ViewPos = origin->InterpolatedPosition(r_TicFracF);
ViewActorPos = origin->Pos();
ViewAngle += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * r_TicFracF);
// Don't let the viewpoint be too close to a floor or ceiling
@ -729,6 +732,7 @@ void GLSectorStackPortal::DrawContents()
FPortal *portal = origin;
ViewPos += origin->mDisplacement;
ViewActorPos += origin->mDisplacement;
GLRenderer->mViewActor = NULL;
// avoid recursions!
@ -772,28 +776,34 @@ void GLSectorStackPortal::DrawContents()
void GLPlaneMirrorPortal::DrawContents()
{
if (renderdepth>r_mirror_recursions)
if (renderdepth > r_mirror_recursions)
{
ClearScreen();
return;
}
// A plane mirror needs to flip the portal exclusion logic because inside the mirror, up is down and down is up.
std::swap(instack[sector_t::floor], instack[sector_t::ceiling]);
int old_pm=PlaneMirrorMode;
int old_pm = PlaneMirrorMode;
// the player is always visible in a mirror.
r_showviewer = true;
double planez = origin->ZatPoint(ViewPos);
ViewPos.Z = 2 * planez - ViewPos.Z;
GLRenderer->mViewActor = NULL;
PlaneMirrorMode = origin->fC() < 0 ? -1 : 1;
PlaneMirrorFlag++;
GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1));
GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1));
ClearClipper();
gl_RenderState.SetClipHeight(planez, PlaneMirrorMode < 0? -1.f : 1.f);
gl_RenderState.SetClipHeight(planez, PlaneMirrorMode < 0 ? -1.f : 1.f);
GLRenderer->DrawScene(DM_PORTAL);
gl_RenderState.SetClipHeight(0.f, 0.f);
PlaneMirrorFlag--;
PlaneMirrorMode=old_pm;
PlaneMirrorMode = old_pm;
std::swap(instack[sector_t::floor], instack[sector_t::ceiling]);
}
void GLPlaneMirrorPortal::PushState()
@ -900,6 +910,8 @@ void GLMirrorPortal::DrawContents()
vertex_t *v1 = linedef->v1;
vertex_t *v2 = linedef->v2;
// the player is always visible in a mirror.
r_showviewer = true;
// Reflect the current view behind the mirror.
if (linedef->Delta().X == 0)
{
@ -996,25 +1008,9 @@ void GLLineToLinePortal::DrawContents()
line_t *origin = glport->lines[0]->mOrigin;
P_TranslatePortalXY(origin, ViewPos.X, ViewPos.Y);
P_TranslatePortalXY(origin, ViewActorPos.X, ViewActorPos.Y);
P_TranslatePortalAngle(origin, ViewAngle);
P_TranslatePortalZ(origin, ViewPos.Z);
P_TranslatePortalXY(origin, ViewPath[0].X, ViewPath[0].Y);
P_TranslatePortalXY(origin, ViewPath[1].X, ViewPath[1].Y);
if (!r_showviewer && camera != nullptr && P_PointOnLineSidePrecise(ViewPath[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(ViewPath[1], glport->lines[0]->mDestination))
{
double distp = (ViewPath[0] - ViewPath[1]).Length();
if (distp > EQUAL_EPSILON)
{
double dist1 = (ViewPos - ViewPath[0]).Length();
double dist2 = (ViewPos - ViewPath[1]).Length();
if (dist1 + dist2 < distp + 1)
{
camera->renderflags |= RF_INVISIBLE;
}
}
}
SaveMapSection();

View file

@ -102,11 +102,12 @@ private:
void DrawPortalStencil();
DVector3 savedViewPos;
DVector3 savedViewActorPos;
DAngle savedAngle;
bool savedshowviewer;
AActor * savedviewactor;
area_t savedviewarea;
ActorRenderFlags savedvisibility;
DVector3 savedviewpath[2];
GLPortal *PrevPortal;
GLPortal *PrevClipPortal;
TArray<BYTE> savedmapsection;

View file

@ -91,6 +91,7 @@ extern bool r_showviewer;
DWORD gl_fixedcolormap;
area_t in_area;
TArray<BYTE> currentmapsection;
int camtexcount;
void gl_ParseDefs();
@ -497,10 +498,6 @@ void FGLRenderer::DrawScene(int drawmode)
if (camera != nullptr)
{
ActorRenderFlags savedflags = camera->renderflags;
if (drawmode != DM_PORTAL && !r_showviewer)
{
camera->renderflags |= RF_INVISIBLE;
}
CreateScene();
camera->renderflags = savedflags;
}
@ -1356,6 +1353,7 @@ void FGLInterface::RenderTextureView (FCanvasTexture *tex, AActor *Viewpoint, in
}
tex->SetUpdated();
camtexcount++;
}
//==========================================================================

View file

@ -75,6 +75,7 @@ EXTERN_CVAR (Float, transsouls)
extern TArray<spritedef_t> sprites;
extern TArray<spriteframe_t> SpriteFrames;
extern TArray<PalEntry> BloodTranslationColors;
extern bool r_showviewer;
enum HWRenderStyle
{
@ -655,7 +656,6 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
if (!(thing->flags & MF_STEALTH) || !gl_fixedcolormap || !gl_enhanced_nightvision || thing == camera)
return;
}
int spritenum = thing->sprite;
DVector2 sprscale = thing->Scale;
if (thing->player != NULL)
@ -670,6 +670,14 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
DVector3 thingpos = thing->InterpolatedPosition(r_TicFracF);
if (thruportal == 1) thingpos += Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
// Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here
if (thing == camera && !r_showviewer)
{
DVector3 thingorigin = thing->Pos();
if (thruportal == 1) thingorigin += Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
if (fabs(thingorigin.X - ViewActorPos.X) < 2 && fabs(thingorigin.Y - ViewActorPos.Y) < 2) return;
}
// Too close to the camera. This doesn't look good if it is a sprite.
if (fabs(thingpos.X - ViewPos.X) < 2 && fabs(thingpos.Y - ViewPos.Y) < 2)
{
@ -916,7 +924,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
OverrideShader = gl_fuzztype + 4;
trans = 0.99f; // trans may not be 1 here
hw_styleflags |= STYLEHW_NoAlphaTest;
hw_styleflags = STYLEHW_NoAlphaTest;
}
else
{
@ -1202,9 +1210,7 @@ void gl_RenderActorsInPortal(FGLLinePortal *glport)
th->Prev += newpos - savedpos;
GLSprite spr;
th->fillcolor = 0xff0000ff;
spr.Process(th, gl_FakeFlat(th->Sector, &fakesector, false), 2);
th->fillcolor = 0xffffffff;
th->Angles.Yaw = savedangle;
th->SetXYZ(savedpos);
th->Prev -= newpos - savedpos;

View file

@ -174,7 +174,6 @@ public:
};
FTextureID topflat,bottomflat;
secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows.
// these are not the same as ytop and ybottom!!!

View file

@ -48,35 +48,6 @@
#include "gl/shaders/gl_shader.h"
//==========================================================================
//
// Checks whether a wall should glow
//
//==========================================================================
void GLWall::CheckGlowing()
{
bottomglowcolor[3] = topglowcolor[3] = 0;
if (!gl_isFullbright(Colormap.LightColor, lightlevel))
{
FTexture *tex = TexMan[topflat];
if (tex != NULL && tex->isGlowing())
{
flags |= GLWall::GLWF_GLOW;
tex->GetGlowColor(topglowcolor);
topglowcolor[3] = tex->gl_info.GlowHeight;
}
tex = TexMan[bottomflat];
if (tex != NULL && tex->isGlowing())
{
flags |= GLWall::GLWF_GLOW;
tex->GetGlowColor(bottomglowcolor);
bottomglowcolor[3] = tex->gl_info.GlowHeight;
}
}
}
//==========================================================================
//
//
@ -111,8 +82,7 @@ void GLWall::PutWall(bool translucent)
if (gltexture == NULL) return;
Colormap.Clear();
}
CheckGlowing();
if (gl_isFullbright(Colormap.LightColor, lightlevel)) flags &= ~GLWF_GLOW;
if (translucent) // translucent walls
{
@ -1544,8 +1514,8 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
RenderStyle = STYLE_Normal;
gltexture = NULL;
topflat = frontsector->GetTexture(sector_t::ceiling); // for glowing textures. These must be saved because
bottomflat = frontsector->GetTexture(sector_t::floor); // the sector passed here might be a temporary copy.
if (gl_GetWallGlow(frontsector, topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
topplane = frontsector->ceilingplane;
bottomplane = frontsector->floorplane;
@ -1781,8 +1751,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t *
RenderStyle = STYLE_Normal;
Colormap = frontsector->ColorMap;
topflat = frontsector->GetTexture(sector_t::ceiling); // for glowing textures
bottomflat = frontsector->GetTexture(sector_t::floor);
if (gl_GetWallGlow(frontsector, topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
topplane = frontsector->ceilingplane;
bottomplane = frontsector->floorplane;
dynlightindex = -1;

View file

@ -207,22 +207,25 @@ void OpenGLFrameBuffer::Update()
//
//==========================================================================
CVAR(Bool, gl_finishbeforeswap, false, 0);
CVAR(Bool, gl_finishbeforeswap, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
extern int camtexcount;
void OpenGLFrameBuffer::Swap()
{
bool swapbefore = gl_finishbeforeswap && camtexcount == 0;
Finish.Reset();
Finish.Clock();
if (gl_finishbeforeswap) glFinish();
if (swapbefore) glFinish();
if (needsetgamma)
{
//DoSetGamma();
needsetgamma = false;
}
SwapBuffers();
if (!gl_finishbeforeswap) glFinish();
if (!swapbefore) glFinish();
Finish.Unclock();
swapped = true;
camtexcount = 0;
FHardwareTexture::UnbindAll();
mDebug->Update();
}

View file

@ -187,6 +187,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F
{
unsigned char * buffer;
int W, H;
int isTransparent = -1;
// Textures that are already scaled in the texture lump will not get replaced
@ -224,14 +225,16 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F
int trans = tex->CopyTrueColorPixels(&imgCreate, exx, exx);
bmp.CopyPixelDataRGB(0, 0, imgCreate.GetPixels(), W, H, 4, W * 4, 0, CF_BGRA);
tex->CheckTrans(buffer, W*H, trans);
bIsTransparent = tex->gl_info.mIsTransparent;
isTransparent = tex->gl_info.mIsTransparent;
if (bIsTransparent == -1) bIsTransparent = isTransparent;
}
}
else if (translation<=0)
{
int trans = tex->CopyTrueColorPixels(&bmp, exx, exx);
tex->CheckTrans(buffer, W*H, trans);
bIsTransparent = tex->gl_info.mIsTransparent;
isTransparent = tex->gl_info.mIsTransparent;
if (bIsTransparent == -1) bIsTransparent = isTransparent;
}
else
{
@ -239,7 +242,8 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F
// Since FTexture's method is doing exactly that by calling GetPixels let's use that here
// to do all the dirty work for us. ;)
tex->FTexture::CopyTrueColorPixels(&bmp, exx, exx);
bIsTransparent = 0;
isTransparent = 0;
// This is not conclusive for setting the texture's transparency info.
}
// if we just want the texture for some checks there's no need for upsampling.
@ -247,7 +251,7 @@ unsigned char * FGLTexture::CreateTexBuffer(int translation, int & w, int & h, F
// [BB] The hqnx upsampling (not the scaleN one) destroys partial transparency, don't upsamle textures using it.
// [BB] Potentially upsample the buffer.
return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, !!bIsTransparent);
return gl_CreateUpsampledTextureBuffer ( tex, buffer, W, H, w, h, !!isTransparent);
}

View file

@ -83,13 +83,23 @@ FCycler::FCycler()
//
//==========================================================================
void FCycler::SetParams(float start, float end, float cycle)
void FCycler::SetParams(float start, float end, float cycle, bool update)
{
m_cycle = cycle;
m_time = 0.f;
m_start = m_current = start;
if (!update || cycle != m_cycle)
{
m_cycle = cycle;
m_time = 0.f;
m_increment = true;
m_current = start;
}
else
{
// When updating and keeping the same cycle, scale the current light size to the new dimensions.
float fact = (m_current - m_start) / (m_end - m_start);
m_current = start + fact *(end - start);
}
m_start = start;
m_end = end;
m_increment = true;
}

View file

@ -22,7 +22,7 @@ class FCycler
public:
FCycler();
void Update(float diff);
void SetParams(float start, float end, float cycle);
void SetParams(float start, float end, float cycle, bool update = false);
void ShouldCycle(bool sc) { m_shouldCycle = sc; }
void SetCycleType(CycleType ct) { m_cycleType = ct; }
float GetVal() { return m_current; }

View file

@ -518,14 +518,12 @@ xx(Alphaceiling)
xx(Renderstylefloor)
xx(Renderstyleceiling)
xx(Waterzone)
xx(portal_ceil_alpha)
xx(portal_ceil_blocksound)
xx(portal_ceil_disabled)
xx(portal_ceil_nopass)
xx(portal_ceil_norender)
xx(portal_ceil_overlaytype)
xx(portal_ceil_useglobaltex)
xx(portal_floor_alpha)
xx(portal_floor_blocksound)
xx(portal_floor_disabled)
xx(portal_floor_nopass)
@ -575,6 +573,13 @@ xx(damageterraineffect)
xx(damagehazard)
xx(floorterrain)
xx(ceilingterrain)
xx(floor_reflect)
xx(ceiling_reflect)
xx(floorglowcolor)
xx(floorglowheight)
xx(ceilingglowcolor)
xx(ceilingglowheight)
xx(fogdensity)
// USDF keywords
xx(Amount)

View file

@ -51,7 +51,7 @@
//
//============================================================================
bool P_Scroll3dMidtex(sector_t *sector, int crush, double move, bool ceiling)
bool P_Scroll3dMidtex(sector_t *sector, int crush, double move, bool ceiling, bool instant)
{
extsector_t::midtex::plane &scrollplane = ceiling? sector->e->Midtex.Ceiling : sector->e->Midtex.Floor;
@ -69,7 +69,7 @@ bool P_Scroll3dMidtex(sector_t *sector, int crush, double move, bool ceiling)
for(unsigned i = 0; i < scrollplane.AttachedSectors.Size(); i++)
{
res |= P_ChangeSector(scrollplane.AttachedSectors[i], crush, move, 2, true);
res |= P_ChangeSector(scrollplane.AttachedSectors[i], crush, move, 2, true, instant);
}
return !res;
}

View file

@ -9,14 +9,14 @@ struct sector_t;
struct line_t;
class AActor;
bool P_Scroll3dMidtex(sector_t *sector, int crush, double move, bool ceiling);
bool P_Scroll3dMidtex(sector_t *sector, int crush, double move, bool ceiling, bool instant = false);
void P_Start3dMidtexInterpolations(TArray<DInterpolation *> &list, sector_t *sec, bool ceiling);
void P_Attach3dMidtexLinesToSector(sector_t *dest, int lineid, int tag, bool ceiling);
bool P_GetMidTexturePosition(const line_t *line, int sideno, double *ptextop, double *ptexbot);
bool P_Check3dMidSwitch(AActor *actor, line_t *line, int side);
bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, struct FLineOpening &open, bool restrict=false);
bool P_MoveLinkedSectors(sector_t *sector, int crush, double move, bool ceiling);
bool P_MoveLinkedSectors(sector_t *sector, int crush, double move, bool ceiling, bool instant = false);
void P_StartLinkedSectorInterpolations(TArray<DInterpolation *> &list, sector_t *sector, bool ceiling);
bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype);
void P_AddSectorLinksByID(sector_t *control, int id, INTBOOL ceiling);

View file

@ -85,6 +85,7 @@
#include "a_pickups.h"
#include "a_armor.h"
#include "a_ammo.h"
#include "r_data/colormaps.h"
extern FILE *Logfile;
@ -343,6 +344,23 @@ FACSStack::~FACSStack()
ACSStringPool GlobalACSStrings;
void ACSStringPool::PoolEntry::Lock()
{
if (Locks.Find(level.levelnum) == Locks.Size())
{
Locks.Push(level.levelnum);
}
}
void ACSStringPool::PoolEntry::Unlock()
{
auto ndx = Locks.Find(level.levelnum);
if (ndx < Locks.Size())
{
Locks.Delete(ndx);
}
}
ACSStringPool::ACSStringPool()
{
memset(PoolBuckets, 0xFF, sizeof(PoolBuckets));
@ -430,7 +448,7 @@ void ACSStringPool::LockString(int strnum)
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
strnum &= ~LIBRARYID_MASK;
assert((unsigned)strnum < Pool.Size());
Pool[strnum].LockCount++;
Pool[strnum].Lock();
}
//============================================================================
@ -446,8 +464,7 @@ void ACSStringPool::UnlockString(int strnum)
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
strnum &= ~LIBRARYID_MASK;
assert((unsigned)strnum < Pool.Size());
assert(Pool[strnum].LockCount > 0);
Pool[strnum].LockCount--;
Pool[strnum].Unlock();
}
//============================================================================
@ -464,7 +481,7 @@ void ACSStringPool::MarkString(int strnum)
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
strnum &= ~LIBRARYID_MASK;
assert((unsigned)strnum < Pool.Size());
Pool[strnum].LockCount |= 0x80000000;
Pool[strnum].Mark = true;
}
//============================================================================
@ -489,7 +506,7 @@ void ACSStringPool::LockStringArray(const int *strnum, unsigned int count)
num &= ~LIBRARYID_MASK;
if ((unsigned)num < Pool.Size())
{
Pool[num].LockCount++;
Pool[num].Lock();
}
}
}
@ -513,8 +530,7 @@ void ACSStringPool::UnlockStringArray(const int *strnum, unsigned int count)
num &= ~LIBRARYID_MASK;
if ((unsigned)num < Pool.Size())
{
assert(Pool[num].LockCount > 0);
Pool[num].LockCount--;
Pool[num].Unlock();
}
}
}
@ -538,7 +554,7 @@ void ACSStringPool::MarkStringArray(const int *strnum, unsigned int count)
num &= ~LIBRARYID_MASK;
if ((unsigned)num < Pool.Size())
{
Pool[num].LockCount |= 0x80000000;
Pool[num].Mark = true;
}
}
}
@ -565,7 +581,7 @@ void ACSStringPool::MarkStringMap(const FWorldGlobalArray &aray)
num &= ~LIBRARYID_MASK;
if ((unsigned)num < Pool.Size())
{
Pool[num].LockCount |= 0x80000000;
Pool[num].Mark |= true;
}
}
}
@ -584,7 +600,8 @@ void ACSStringPool::UnlockAll()
{
for (unsigned int i = 0; i < Pool.Size(); ++i)
{
Pool[i].LockCount = 0;
Pool[i].Mark = false;
Pool[i].Locks.Clear();
}
}
@ -607,7 +624,7 @@ void ACSStringPool::PurgeStrings()
PoolEntry *entry = &Pool[i];
if (entry->Next != FREE_ENTRY)
{
if (entry->LockCount == 0)
if (entry->Locks.Size() == 0 && !entry->Mark)
{
freedcount++;
// Mark this entry as free.
@ -627,7 +644,7 @@ void ACSStringPool::PurgeStrings()
entry->Next = PoolBuckets[h];
PoolBuckets[h] = i;
// Remove MarkString's mark.
entry->LockCount &= 0x7FFFFFFF;
entry->Mark = false;
}
}
}
@ -692,7 +709,8 @@ int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucke
entry->Str = str;
entry->Hash = h;
entry->Next = PoolBuckets[bucketnum];
entry->LockCount = 0;
entry->Mark = false;
entry->Locks.Clear();
PoolBuckets[bucketnum] = index;
return index | STRPOOL_LIBRARYID_OR;
}
@ -735,7 +753,8 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
for (auto &p : Pool)
{
p.Next = FREE_ENTRY;
p.LockCount = 0;
p.Mark = false;
p.Locks.Clear();
}
if (file.BeginArray("pool"))
{
@ -749,7 +768,7 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
if (ii < Pool.Size())
{
file("string", Pool[ii].Str)
("lockcount", Pool[ii].LockCount);
("locks", Pool[ii].Locks);
unsigned h = SuperFastHash(Pool[ii].Str, Pool[ii].Str.Len());
unsigned bucketnum = h % NUM_BUCKETS;
@ -792,13 +811,9 @@ void ACSStringPool::WriteStrings(FSerializer &file, const char *key) const
{
if (file.BeginObject(nullptr))
{
if (i == 430)
{
int a = 0;
}
file("index", i)
("string", entry->Str)
("lockcount", entry->LockCount)
("locks", entry->Locks)
.EndObject();
}
}
@ -823,12 +838,28 @@ void ACSStringPool::Dump() const
{
if (Pool[i].Next != FREE_ENTRY)
{
Printf("%4u. (%2d) \"%s\"\n", i, Pool[i].LockCount, Pool[i].Str.GetChars());
Printf("%4u. (%2d) \"%s\"\n", i, Pool[i].Locks.Size(), Pool[i].Str.GetChars());
}
}
Printf("First free %u\n", FirstFreeEntry);
}
void ACSStringPool::UnlockForLevel(int lnum)
{
for (unsigned int i = 0; i < Pool.Size(); ++i)
{
if (Pool[i].Next != FREE_ENTRY)
{
auto ndx = Pool[i].Locks.Find(lnum);
if (ndx < Pool[i].Locks.Size())
{
Pool[i].Locks.Delete(ndx);
}
}
}
}
//============================================================================
//
// P_MarkWorldVarStrings
@ -1573,19 +1604,7 @@ void FBehavior::StaticLockLevelVarStrings()
void FBehavior::StaticUnlockLevelVarStrings()
{
// Unlock map variables.
for (DWORD modnum = 0; modnum < StaticModules.Size(); ++modnum)
{
StaticModules[modnum]->UnlockMapVarStrings();
}
// Unlock running scripts' local variables.
if (DACSThinker::ActiveThinker != NULL)
{
for (DLevelScript *script = DACSThinker::ActiveThinker->Scripts; script != NULL; script = script->GetNext())
{
script->UnlockLocalVarStrings();
}
}
GlobalACSStrings.UnlockForLevel(level.levelnum);
}
void FBehavior::MarkMapVarStrings() const
@ -4393,6 +4412,11 @@ enum EACSFunctions
ACSF_SetActorFlag,
ACSF_SetTranslation,
// OpenGL stuff
ACSF_SetSectorGlow = 400,
ACSF_SetFogDensity,
// ZDaemon
ACSF_GetTeamScore = 19620, // (int team)
ACSF_SetTeamScore, // (int team, int value
@ -6047,6 +6071,38 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
return 1;
}
// OpenGL exclusive functions
case ACSF_SetSectorGlow:
{
int which = !!args[1];
PalEntry color(args[2], args[3], args[4]);
float height = float(args[5]);
if (args[2] == -1) color = -1;
FSectorTagIterator it(args[0]);
int s;
while ((s = it.Next()) >= 0)
{
sectors[s].planes[which].GlowColor = color;
sectors[s].planes[which].GlowHeight = height;
}
break;
}
case ACSF_SetFogDensity:
{
FSectorTagIterator it(args[0]);
int s;
int d = clamp(args[1]/2, 0, 255);
while ((s = it.Next()) >= 0)
{
auto f = sectors[s].ColorMap->Fade;
sectors[s].ColorMap = GetSpecialLights(sectors[s].ColorMap->Color, PalEntry(d, f.r, f.g, f.b), sectors[s].ColorMap->Desaturate);
}
break;
}
default:
break;
}

View file

@ -95,6 +95,7 @@ public:
void PurgeStrings();
void Clear();
void Dump() const;
void UnlockForLevel(int level) ;
void ReadStrings(FSerializer &file, const char *key);
void WriteStrings(FSerializer &file, const char *key) const;
@ -112,7 +113,11 @@ private:
FString Str;
unsigned int Hash;
unsigned int Next;
unsigned int LockCount;
bool Mark;
TArray<int> Locks;
void Lock();
void Unlock();
};
TArray<PoolEntry> Pool;
unsigned int PoolBuckets[NUM_BUCKETS];

View file

@ -1286,9 +1286,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode)
{
ang = i*360./nails;
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
P_LineAttack (self, ang, MISSILERANGE, 0.,
P_LineAttack(self, ang, MISSILERANGE, 0.,
//P_AimLineAttack (self, ang, MISSILERANGE),
naildamage, NAME_Hitscan, pufftype);
naildamage, NAME_Hitscan, pufftype, (self->flags & MF_MISSILE) ? LAF_TARGETISSOURCE : 0);
}
}
@ -1454,10 +1454,11 @@ enum CM_Flags
CMF_OFFSETPITCH = 32,
CMF_SAVEPITCH = 64,
CMF_ABSOLUTEANGLE = 128
CMF_ABSOLUTEANGLE = 128,
CMF_BADPITCH = 256
};
DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile)
DEFINE_ACTION_FUNCTION(AActor, A_SpawnProjectile)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_CLASS (ti, AActor);
@ -1525,6 +1526,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomMissile)
}
missilespeed = fabs(Pitch.Cos() * missile->Speed);
missile->Vel.Z = Pitch.Sin() * missile->Speed;
if (!(flags & CMF_BADPITCH)) missile->Vel.Z *= -1;
}
else
{
@ -1831,7 +1833,7 @@ static void AimBulletMissile(AActor *proj, AActor *puff, int flags, bool temp, b
// Aim for the base of the puff as that's where blood puffs will spawn... roughly.
A_Face(proj, puff, 0., 0., 0., 0., 1);
proj->Vel3DFromAngle(-proj->Angles.Pitch, proj->Speed);
proj->Vel3DFromAngle(proj->Angles.Pitch, proj->Speed);
if (!temp)
{
@ -1986,7 +1988,7 @@ enum FP_Flags
FPF_TRANSFERTRANSLATION = 2,
FPF_NOAUTOAIM = 4,
};
DEFINE_ACTION_FUNCTION(AStateProvider, A_FireCustomMissile)
DEFINE_ACTION_FUNCTION(AStateProvider, A_FireProjectile)
{
PARAM_ACTION_PROLOGUE(AStateProvider);
PARAM_CLASS (ti, AActor);
@ -2300,7 +2302,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun)
// We probably won't hit the target, but aim at it anyway so we don't look stupid.
DVector2 xydiff = self->Vec2To(self->target);
double zdiff = self->target->Center() - self->Center() - self->Floorclip;
self->Angles.Pitch = VecToAngle(xydiff.Length(), zdiff);
self->Angles.Pitch = -VecToAngle(xydiff.Length(), zdiff);
}
// Let the aim trail behind the player
if (aim)
@ -5227,12 +5229,13 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist)
}
else
{
self->UnlinkFromWorld ();
FLinkContext ctx;
self->UnlinkFromWorld (&ctx);
self->flags |= MF_NOBLOCKMAP;
// We need to do portal offsetting here explicitly, because SetXY cannot do that.
newpos -= self->Pos().XY();
self->SetXY(self->Vec2Offset(newpos.X, newpos.Y));
self->LinkToWorld ();
self->LinkToWorld (&ctx);
}
self->WeaveIndexXY = weaveXY;
}
@ -6688,10 +6691,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_FaceMovementDirection)
{
DAngle current = mobj->Angles.Pitch;
const DVector2 velocity = mobj->Vel.XY();
DAngle pitch = VecToAngle(velocity.Length(), mobj->Vel.Z);
DAngle pitch = -VecToAngle(velocity.Length(), mobj->Vel.Z);
if (pitchlimit > 0)
{
DAngle pdelta = deltaangle(-current, pitch);
DAngle pdelta = deltaangle(current, pitch);
if (fabs(pdelta) > pitchlimit)
{
@ -6860,17 +6863,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetSize)
double oldradius = self->radius;
double oldheight = self->Height;
self->UnlinkFromWorld();
FLinkContext ctx;
self->UnlinkFromWorld(&ctx);
self->radius = newradius;
self->Height = newheight;
self->LinkToWorld();
self->LinkToWorld(&ctx);
if (testpos && !P_TestMobjLocation(self))
{
self->UnlinkFromWorld();
self->UnlinkFromWorld(&ctx);
self->radius = oldradius;
self->Height = oldheight;
self->LinkToWorld();
self->LinkToWorld(&ctx);
ACTION_RETURN_BOOL(false);
}

View file

@ -87,7 +87,8 @@ void DFloor::Serialize(FSerializer &arc)
("pausetime", m_PauseTime)
("steptime", m_StepTime)
("persteptime", m_PerStepTime)
("crushmode", m_Hexencrush);
("crushmode", m_Hexencrush)
("instant", m_Instant);
}
//==========================================================================
@ -130,7 +131,7 @@ void DFloor::Tick ()
if (m_Type == waitStair)
return;
res = m_Sector->MoveFloor (m_Speed, m_FloorDestDist, m_Crush, m_Direction, m_Hexencrush);
res = m_Sector->MoveFloor (m_Speed, m_FloorDestDist, m_Crush, m_Direction, m_Hexencrush, m_Instant);
if (res == EMoveResult::pastdest)
{
@ -287,6 +288,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
floor->m_Speed = speed;
floor->m_ResetCount = 0; // [RH]
floor->m_OrgDist = sec->floorplane.fD(); // [RH]
floor->m_Instant = false;
switch (floortype)
{
@ -452,6 +454,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line,
(floor->m_Speed >= fabs(sec->floorplane.fD() - floor->m_FloorDestDist))) // moving in one step
{
floor->StopInterpolation(true);
floor->m_Instant = true;
// [Graf Zahl]
// Don't make sounds for instant movement hacks but make an exception for

View file

@ -1546,7 +1546,7 @@ dopain:
target->SetState (target->SeeState);
}
}
else if (source != target->target && target->OkayToSwitchTarget (source))
else if ((damage > 0 || fakedPain) && source != target->target && target->OkayToSwitchTarget (source))
{
// Target actor is not intent on another actor,
// so make him chase after source

View file

@ -93,12 +93,12 @@ bool sector_t::IsLinked(sector_t *other, bool ceiling) const
//
//============================================================================
static bool MoveCeiling(sector_t *sector, int crush, double move)
static bool MoveCeiling(sector_t *sector, int crush, double move, bool instant)
{
sector->ceilingplane.ChangeHeight (move);
sector->ChangePlaneTexZ(sector_t::ceiling, move);
if (P_ChangeSector(sector, crush, move, 1, true)) return false;
if (P_ChangeSector(sector, crush, move, 1, true, instant)) return false;
// Don't let the ceiling go below the floor
if (!sector->ceilingplane.isSlope() && !sector->floorplane.isSlope() &&
@ -108,12 +108,12 @@ static bool MoveCeiling(sector_t *sector, int crush, double move)
return true;
}
static bool MoveFloor(sector_t *sector, int crush, double move)
static bool MoveFloor(sector_t *sector, int crush, double move, bool instant)
{
sector->floorplane.ChangeHeight (move);
sector->ChangePlaneTexZ(sector_t::floor, move);
if (P_ChangeSector(sector, crush, move, 0, true)) return false;
if (P_ChangeSector(sector, crush, move, 0, true, instant)) return false;
// Don't let the floor go above the ceiling
if (!sector->ceilingplane.isSlope() && !sector->floorplane.isSlope() &&
@ -133,7 +133,7 @@ static bool MoveFloor(sector_t *sector, int crush, double move)
//
//============================================================================
bool P_MoveLinkedSectors(sector_t *sector, int crush, double move, bool ceiling)
bool P_MoveLinkedSectors(sector_t *sector, int crush, double move, bool ceiling, bool instant)
{
extsector_t::linked::plane &scrollplane = ceiling? sector->e->Linked.Ceiling : sector->e->Linked.Floor;
bool ok = true;
@ -143,55 +143,55 @@ bool P_MoveLinkedSectors(sector_t *sector, int crush, double move, bool ceiling)
switch(scrollplane.Sectors[i].Type)
{
case LINK_FLOOR:
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move, instant);
break;
case LINK_CEILING:
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move, instant);
break;
case LINK_BOTH:
if (move < 0)
{
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move, instant);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move, instant);
}
else
{
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move, instant);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move, instant);
}
break;
case LINK_FLOORMIRROR:
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move, instant);
break;
case LINK_CEILINGMIRROR:
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move, instant);
break;
case LINK_BOTHMIRROR:
if (move > 0)
{
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move, instant);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move, instant);
}
else
{
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move, instant);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move, instant);
}
break;
case LINK_FLOOR+LINK_CEILINGMIRROR:
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, move, instant);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, -move, instant);
break;
case LINK_CEILING+LINK_FLOORMIRROR:
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move);
ok &= MoveFloor(scrollplane.Sectors[i].Sector, crush, -move, instant);
ok &= MoveCeiling(scrollplane.Sectors[i].Sector, crush, move, instant);
break;
default:

View file

@ -246,10 +246,6 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false,
//
// If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz".
extern msecnode_t *sector_list; // phares 3/16/98
struct spechit_t
{
line_t *line;
@ -308,7 +304,7 @@ enum
};
void P_FindFloorCeiling (AActor *actor, int flags=0);
bool P_ChangeSector (sector_t* sector, int crunch, double amt, int floorOrCeil, bool isreset);
bool P_ChangeSector (sector_t* sector, int crunch, double amt, int floorOrCeil, bool isreset, bool instant = false);
DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLineTarget *pLineTarget = NULL, DAngle vrange = 0., int flags = 0, AActor *target = NULL, AActor *friender = NULL);
@ -328,6 +324,7 @@ enum // P_LineAttack flags
LAF_NORANDOMPUFFZ = 2,
LAF_NOIMPACTDECAL = 4,
LAF_NOINTERACT = 8,
LAF_TARGETISSOURCE = 16,
};
AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL);
@ -396,11 +393,10 @@ enum
int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
FName damageType, int flags, int fulldamagedistance=0);
void P_DelSector_List();
void P_DelSeclist(msecnode_t *); // phares 3/16/98
void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead);
msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist);
msecnode_t* P_DelSecnode(msecnode_t *, msecnode_t *sector_t::*head);
void P_CreateSecNodeList(AActor*); // phares 3/14/98
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead);
double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98
double P_GetFriction(const AActor *mo, double *frictionfactor);

View file

@ -25,6 +25,7 @@
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include "templates.h"
@ -82,8 +83,55 @@ static FRandom pr_crunch("DoCrunch");
TArray<spechit_t> spechit;
TArray<spechit_t> portalhit;
// Temporary holder for thing_sectorlist threads
msecnode_t* sector_list = NULL; // phares 3/16/98
//==========================================================================
//
// CanCollideWith
//
// Checks if an actor can collide with another one, calling virtual script functions to check.
//
//==========================================================================
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
{
// No need to check the parameters, as they are not even used.
ACTION_RETURN_BOOL(true);
}
bool P_CanCollideWith(AActor *tmthing, AActor *thing)
{
static unsigned VIndex = ~0u;
if (VIndex == ~0u)
{
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith");
assert(VIndex != ~0u);
}
VMValue params[3] = { tmthing, thing, false };
VMReturn ret;
int retval;
ret.IntAt(&retval);
auto clss = tmthing->GetClass();
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return false;
}
std::swap(params[0].a, params[1].a);
params[2].i = true;
// re-get for the other actor.
clss = thing->GetClass();
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return false;
}
return true;
}
//==========================================================================
//
@ -405,6 +453,13 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi
}
}
if (!P_CanCollideWith(tmf.thing, th))
continue;
// Don't let players and monsters block item teleports (all other actor types will still block.)
if (thing->IsKindOf(RUNTIME_CLASS(AInventory)) && !(thing->flags & MF_SOLID) && ((th->flags3 & MF3_ISMONSTER) || th->player != nullptr))
continue;
// monsters don't stomp things except on boss level
// [RH] Some Heretic/Hexen monsters can telestomp
// ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them.
@ -1150,12 +1205,6 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter)
//
//==========================================================================
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
{
// No need to check the parameters, as they are not even used.
ACTION_RETURN_BOOL(true);
}
bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::CheckResult &cres, const FBoundingBox &box, FCheckPosition &tm)
{
AActor *thing = cres.thing;
@ -1260,36 +1309,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
if (((thing->flags & MF_SOLID) || (thing->flags6 & (MF6_TOUCHY | MF6_BUMPSPECIAL))) &&
((tm.thing->flags & (MF_SOLID|MF_MISSILE)) || (tm.thing->flags2 & MF2_BLASTED) || (tm.thing->flags6 & MF6_BLOCKEDBYSOLIDACTORS) || (tm.thing->BounceFlags & BOUNCE_MBF)))
{
static unsigned VIndex = ~0u;
if (VIndex == ~0u)
{
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanCollideWith");
assert(VIndex != ~0u);
}
VMValue params[3] = { tm.thing, thing, false };
VMReturn ret;
int retval;
ret.IntAt(&retval);
auto clss = tm.thing->GetClass();
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return true;
}
std::swap(params[0].a, params[1].a);
params[2].i = true;
// re-get for the other actor.
clss = thing->GetClass();
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
if (func != nullptr)
{
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
if (!retval) return true;
}
if (!P_CanCollideWith(tm.thing, thing)) return true;
}
@ -1962,6 +1982,12 @@ bool P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj)
{ // something higher is in the way
continue;
}
else if (!P_CanCollideWith(actor, thing))
{ // If they cannot collide, they cannot block each other.
continue;
}
onmobj = thing;
if (quick) break;
}
@ -2390,10 +2416,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
FLinePortal *port = ld->getPortal();
if (port->mType == PORTT_LINKED)
{
thing->UnlinkFromWorld();
FLinkContext ctx;
thing->UnlinkFromWorld(&ctx);
thing->SetXY(tm.pos + port->mDisplacement);
thing->Prev += port->mDisplacement;
thing->LinkToWorld();
thing->LinkToWorld(&ctx);
P_FindFloorCeiling(thing);
portalcrossed = true;
tm.portalstep = false;
@ -2414,11 +2441,12 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
thing->flags6 &= ~MF6_INTRYMOVE;
return false;
}
thing->UnlinkFromWorld();
FLinkContext ctx;
thing->UnlinkFromWorld(&ctx);
thing->SetXYZ(pos);
P_TranslatePortalVXVY(ld, thing->Vel.X, thing->Vel.Y);
P_TranslatePortalAngle(ld, thing->Angles.Yaw);
thing->LinkToWorld();
thing->LinkToWorld(&ctx);
P_FindFloorCeiling(thing);
thing->ClearInterpolation();
portalcrossed = true;
@ -2459,7 +2487,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
if (!portalcrossed)
{
// the move is ok, so link the thing into its new position
thing->UnlinkFromWorld();
FLinkContext ctx;
thing->UnlinkFromWorld(&ctx);
oldsector = thing->Sector;
thing->floorz = tm.floorz;
@ -2472,7 +2501,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
thing->ceilingsector = tm.ceilingsector;
thing->SetXY(pos);
thing->LinkToWorld();
thing->LinkToWorld(&ctx);
}
if (thing->flags2 & MF2_FLOORCLIP)
@ -2565,13 +2594,14 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
// If the actor stepped through a ceiling portal we need to reacquire the actual position info after the transition
if (tm.portalstep)
{
FLinkContext ctx;
DVector3 oldpos = thing->Pos();
thing->UnlinkFromWorld();
thing->UnlinkFromWorld(&ctx);
thing->SetXYZ(thing->PosRelative(thing->Sector->GetOppositePortalGroup(sector_t::ceiling)));
thing->Prev = thing->Pos() - oldpos;
thing->Sector = P_PointInSector(thing->Pos());
thing->PrevPortalGroup = thing->Sector->PortalGroup;
thing->LinkToWorld();
thing->LinkToWorld(&ctx);
P_FindFloorCeiling(thing);
}
@ -4475,7 +4505,9 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
puff = P_SpawnPuff(t1, pufftype, bleedpos, 0., 0., 2, puffFlags | PF_HITTHING | PF_TEMPORARY);
killPuff = true;
}
newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags|DMG_USEANGLE, trace.SrcAngleFromTarget);
auto src = t1;
if ((flags & LAF_TARGETISSOURCE) && t1 && t1->target) src = t1->target;
newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, src, damage, damageType, dmgflags|DMG_USEANGLE, trace.SrcAngleFromTarget);
if (actualdamage != NULL)
{
*actualdamage = newdam;
@ -4921,10 +4953,10 @@ void P_RailAttack(FRailParams *p)
}
AActor *source = p->source;
DAngle pitch = -source->Angles.Pitch + p->pitchoffset;
DAngle pitch = source->Angles.Pitch + p->pitchoffset;
DAngle angle = source->Angles.Yaw + p->angleoffset;
DVector3 vec(DRotator(pitch, angle, angle));
DVector3 vec(DRotator(-pitch, angle, angle));
double shootz = source->Center() - source->FloatSpeed + p->offset_z;
if (!(p->flags & RAF_CENTERZ))
@ -5682,6 +5714,7 @@ struct FChangePosition
int crushchange;
bool nofit;
bool movemidtex;
bool instant;
};
TArray<AActor *> intersectors;
@ -5942,6 +5975,9 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
continue;
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
continue;
if (!P_CanCollideWith(thing, intersect))
continue;
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
@ -5959,6 +5995,12 @@ int P_PushUp(AActor *thing, FChangePosition *cpos)
intersect->SetZ(oldz);
return 2;
}
if (cpos->instant)
{
intersect->Prev.Z += intersect->Z() - oldz;
if (intersect->CheckLocalView(consoleplayer)) R_ResetViewInterpolation();
}
intersect->UpdateRenderSectorList();
}
thing->CheckPortalTransition(true);
@ -5988,6 +6030,18 @@ int P_PushDown(AActor *thing, FChangePosition *cpos)
for (; firstintersect < lastintersect; firstintersect++)
{
AActor *intersect = intersectors[firstintersect];
// [GZ] Skip this iteration for THRUSPECIES things
// Should there be MF2_THRUGHOST / MF3_GHOST checks there too for consistency?
// Or would that risk breaking established behavior? THRUGHOST, like MTHRUSPECIES,
// is normally for projectiles which would have exploded by now anyway...
if (thing->flags6 & MF6_THRUSPECIES && thing->GetSpecies() == intersect->GetSpecies())
continue;
if ((thing->flags & MF_MISSILE) && (intersect->flags2 & MF2_REFLECTIVE) && (intersect->flags7 & MF7_THRUREFLECT))
continue;
if (!P_CanCollideWith(thing, intersect))
continue;
if (!(intersect->flags2 & MF2_PASSMOBJ) ||
(!(intersect->flags3 & MF3_ISMONSTER) && intersect->Mass > mymass) ||
(intersect->flags4 & MF4_ACTLIKEBRIDGE)
@ -6038,6 +6092,11 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
(((cpos->sector->Flags & SECF_FLOORDROP) || cpos->moveamt < 9)
&& thing->Z() - thing->floorz <= cpos->moveamt))
{
if (cpos->instant)
{
thing->Prev.Z += thing->floorz - oldz;
if (thing->CheckLocalView(consoleplayer)) R_ResetViewInterpolation();
}
thing->SetZ(thing->floorz);
P_CheckFakeFloorTriggers(thing, oldz);
thing->UpdateRenderSectorList();
@ -6047,6 +6106,11 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
{
if ((thing->flags & MF_NOGRAVITY) && (thing->flags6 & MF6_RELATIVETOFLOOR))
{
if (cpos->instant)
{
thing->Prev.Z += -oldfloorz + thing->floorz;
if (thing->CheckLocalView(consoleplayer)) R_ResetViewInterpolation();
}
thing->AddZ(-oldfloorz + thing->floorz);
P_CheckFakeFloorTriggers(thing, oldz);
thing->UpdateRenderSectorList();
@ -6082,6 +6146,12 @@ void PIT_FloorRaise(AActor *thing, FChangePosition *cpos)
return; // do not move bridge things
}
intersectors.Clear();
if (cpos->instant)
{
thing->Prev.Z += thing->floorz - thing->Z();
if (thing->CheckLocalView(consoleplayer)) R_ResetViewInterpolation();
}
thing->SetZ(thing->floorz);
}
else
@ -6090,6 +6160,11 @@ void PIT_FloorRaise(AActor *thing, FChangePosition *cpos)
{
intersectors.Clear();
thing->AddZ(-oldfloorz + thing->floorz);
if (cpos->instant)
{
thing->Prev.Z += -oldfloorz + thing->floorz;
if (thing->CheckLocalView(consoleplayer)) R_ResetViewInterpolation();
}
}
else return;
}
@ -6222,7 +6297,7 @@ void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos)
//
//=============================================================================
bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, bool isreset)
bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, bool isreset, bool instant)
{
FChangePosition cpos;
void(*iterator)(AActor *, FChangePosition *);
@ -6234,6 +6309,7 @@ bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, b
cpos.moveamt = fabs(amt);
cpos.movemidtex = false;
cpos.sector = sector;
cpos.instant = instant;
// Also process all sectors that have 3D floors transferred from the
// changed sector.
@ -6532,23 +6608,6 @@ msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead)
return NULL;
} // phares 3/13/98
//=============================================================================
//
// P_DelSector_List
//
// Deletes the sector_list and NULLs it.
//
//=============================================================================
void P_DelSector_List()
{
if (sector_list != NULL)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
}
//=============================================================================
//
// P_DelSeclist
@ -6557,10 +6616,10 @@ void P_DelSector_List()
//
//=============================================================================
void P_DelSeclist(msecnode_t *node)
void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead)
{
while (node)
node = P_DelSecnode(node, &sector_t::touching_thinglist);
node = P_DelSecnode(node, sechead);
}
//=============================================================================
@ -6572,7 +6631,7 @@ void P_DelSeclist(msecnode_t *node)
//
//=============================================================================
void P_CreateSecNodeList(AActor *thing)
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead)
{
msecnode_t *node;
@ -6588,7 +6647,7 @@ void P_CreateSecNodeList(AActor *thing)
node = node->m_tnext;
}
FBoundingBox box(thing->X(), thing->Y(), thing->radius);
FBoundingBox box(thing->X(), thing->Y(), radius);
FBlockLinesIterator it(box);
line_t *ld;
@ -6604,7 +6663,7 @@ void P_CreateSecNodeList(AActor *thing)
// allowed to move to this position, then the sector_list
// will be attached to the Thing's AActor at touching_sectorlist.
sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->touching_thinglist);
sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead);
// Don't assume all lines are 2-sided, since some Things
// like MT_TFOG are allowed regardless of whether their radius takes
@ -6614,12 +6673,12 @@ void P_CreateSecNodeList(AActor *thing)
// Use sidedefs instead of 2s flag to determine two-sidedness.
if (ld->backsector)
sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->touching_thinglist);
sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead);
}
// Add the sector of the (x,y) point to sector_list.
sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->touching_thinglist);
sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead);
// Now delete any nodes that won't be used. These are the ones where
// m_thing is still NULL.
@ -6631,16 +6690,16 @@ void P_CreateSecNodeList(AActor *thing)
{
if (node == sector_list)
sector_list = node->m_tnext;
node = P_DelSecnode(node, &sector_t::touching_thinglist);
node = P_DelSecnode(node, seclisthead);
}
else
{
node = node->m_tnext;
}
}
return sector_list;
}
//=============================================================================
//
// P_DelPortalnode
@ -6771,6 +6830,7 @@ void AActor::UpdateRenderSectorList()
sec = P_PointInSector(newpos);
render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist);
}
sec = Sector;
lasth = FLT_MAX;
while (!sec->PortalBlocksMovement(sector_t::floor))
{

View file

@ -243,9 +243,9 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co
//
//==========================================================================
void AActor::UnlinkFromWorld ()
void AActor::UnlinkFromWorld (FLinkContext *ctx)
{
sector_list = NULL;
if (ctx != nullptr) ctx->sector_list = nullptr;
if (!(flags & MF_NOSECTOR))
{
// invisible things don't need to be in sector list
@ -272,12 +272,19 @@ void AActor::UnlinkFromWorld ()
// put it back into touching_sectorlist. It's done this way to
// avoid a lot of deleting/creating for nodes, when most of the
// time you just get back what you deleted anyway.
//
// If this Thing is being removed entirely, then the calling
// routine will clear out the nodes in sector_list.
sector_list = touching_sectorlist;
touching_sectorlist = NULL; //to be restored by P_SetThingPosition
if (ctx != nullptr)
{
ctx->sector_list = touching_sectorlist;
ctx->render_list = touching_rendersectors;
}
else
{
P_DelSeclist(touching_sectorlist, &sector_t::touching_thinglist);
P_DelSeclist(touching_rendersectors, &sector_t::touching_renderthings);
}
touching_sectorlist = nullptr; //to be restored by P_SetThingPosition
touching_rendersectors = nullptr;
}
}
@ -389,7 +396,7 @@ bool AActor::FixMapthingPos()
DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld)
{
PARAM_SELF_PROLOGUE(AActor);
self->UnlinkFromWorld();
self->UnlinkFromWorld(nullptr); // fixme
return 0;
}
@ -402,7 +409,7 @@ DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld)
//
//==========================================================================
void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sector)
{
bool spawning = spawningmapthing;
@ -454,9 +461,13 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
// When a node is deleted, its sector links (the links starting
// at sector_t->touching_thinglist) are broken. When a node is
// added, new sector links are created.
P_CreateSecNodeList(this);
touching_sectorlist = sector_list; // Attach to thing
sector_list = NULL; // clear for next time
touching_sectorlist = P_CreateSecNodeList(this, radius, ctx != nullptr? ctx->sector_list : nullptr, &sector_t::touching_thinglist); // Attach to thing
if (renderradius >= 0) touching_rendersectors = P_CreateSecNodeList(this, MAX(radius, renderradius), ctx != nullptr ? ctx->render_list : nullptr, &sector_t::touching_renderthings);
else
{
touching_rendersectors = nullptr;
if (ctx != nullptr) P_DelSeclist(ctx->render_list, &sector_t::touching_renderthings);
}
}
@ -519,15 +530,16 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector)
DEFINE_ACTION_FUNCTION(AActor, LinkToWorld)
{
PARAM_SELF_PROLOGUE(AActor);
self->LinkToWorld();
self->LinkToWorld(nullptr); // fixme
return 0;
}
void AActor::SetOrigin(double x, double y, double z, bool moving)
{
UnlinkFromWorld ();
FLinkContext ctx;
UnlinkFromWorld (&ctx);
SetXYZ(x, y, z);
LinkToWorld ();
LinkToWorld (&ctx);
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS);
if (!moving) ClearInterpolation();
}

View file

@ -205,6 +205,7 @@ DEFINE_FIELD(AActor, ceilingsector)
DEFINE_FIELD(AActor, ceilingpic)
DEFINE_FIELD(AActor, Height)
DEFINE_FIELD(AActor, radius)
DEFINE_FIELD(AActor, renderradius)
DEFINE_FIELD(AActor, projectilepassheight)
DEFINE_FIELD(AActor, tics)
DEFINE_FIELD_NAMED(AActor, state, curstate) // clashes with type 'state'.
@ -374,6 +375,7 @@ void AActor::Serialize(FSerializer &arc)
A("floorsector", floorsector)
A("ceilingsector", ceilingsector)
A("radius", radius)
A("renderradius", renderradius)
A("height", Height)
A("ppassheight", projectilepassheight)
A("vel", Vel)
@ -510,8 +512,9 @@ void AActor::Serialize(FSerializer &arc)
void AActor::PostSerialize()
{
touching_sectorlist = NULL;
LinkToWorld(false, Sector);
touching_sectorlist = nullptr;
touching_rendersectors = nullptr;
LinkToWorld(nullptr, false, Sector);
AddToHash();
if (player)
@ -3687,12 +3690,13 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec)
void AActor::CheckPortalTransition(bool islinked)
{
bool moved = false;
FLinkContext ctx;
while (!Sector->PortalBlocksMovement(sector_t::ceiling))
{
if (Z() >= Sector->GetPortalPlaneZ(sector_t::ceiling))
{
DVector3 oldpos = Pos();
if (islinked && !moved) UnlinkFromWorld();
if (islinked && !moved) UnlinkFromWorld(&ctx);
SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::ceiling)));
Prev = Pos() - oldpos;
Sector = P_PointInSector(Pos());
@ -3709,7 +3713,7 @@ void AActor::CheckPortalTransition(bool islinked)
if (Z() < portalz && floorz < portalz)
{
DVector3 oldpos = Pos();
if (islinked && !moved) UnlinkFromWorld();
if (islinked && !moved) UnlinkFromWorld(&ctx);
SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::floor)));
Prev = Pos() - oldpos;
Sector = P_PointInSector(Pos());
@ -3719,7 +3723,7 @@ void AActor::CheckPortalTransition(bool islinked)
else break;
}
}
if (islinked && moved) LinkToWorld();
if (islinked && moved) LinkToWorld(&ctx);
}
//
@ -3782,11 +3786,12 @@ void AActor::Tick ()
if (!Vel.isZero() || !(flags & MF_NOBLOCKMAP))
{
UnlinkFromWorld();
FLinkContext ctx;
UnlinkFromWorld(&ctx);
flags |= MF_NOBLOCKMAP;
SetXYZ(Vec3Offset(Vel));
CheckPortalTransition(false);
LinkToWorld();
LinkToWorld(&ctx);
}
}
else
@ -4544,12 +4549,13 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a
actor->sprite = st->sprite;
actor->frame = st->GetFrame();
actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright());
actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
actor->touching_sectorlist = nullptr; // NULL head of sector list // phares 3/13/98
actor->touching_rendersectors = nullptr;
if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0)
actor->Speed = actor->GetClass()->FastSpeed;
// set subsector and/or block links
actor->LinkToWorld (SpawningMapThing);
actor->LinkToWorld (nullptr, SpawningMapThing);
actor->ClearInterpolation();
actor->dropoffz = actor->floorz = actor->Sector->floorplane.ZatPoint(pos);
@ -4926,12 +4932,9 @@ void AActor::Destroy ()
RemoveFromHash ();
// unlink from sector and block lists
UnlinkFromWorld ();
UnlinkFromWorld (nullptr);
flags |= MF_NOSECTOR|MF_NOBLOCKMAP;
// Delete all nodes on the current sector_list phares 3/16/98
P_DelSector_List();
// Transform any playing sound into positioned, non-actor sounds.
S_RelinkSound (this, NULL);
@ -6322,7 +6325,7 @@ bool P_CheckMissileSpawn (AActor* th, double maxdist)
// [RH] Don't explode ripping missiles that spawn inside something
if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP))
{
// If this is a monster spawned by A_CustomMissile subtract it from the counter.
// If this is a monster spawned by A_SpawnProjectile subtract it from the counter.
th->ClearCounters();
// [RH] Don't explode missiles that spawn on top of horizon lines
if (th->BlockingLine != NULL && th->BlockingLine->special == Line_Horizon)
@ -7482,9 +7485,10 @@ void AActor::RestoreSpecialPosition()
// Move item back to its original location
DVector2 sp = SpawnPoint;
UnlinkFromWorld();
FLinkContext ctx;
UnlinkFromWorld(&ctx);
SetXY(sp);
LinkToWorld(true);
LinkToWorld(&ctx, true);
SetZ(Sector->floorplane.ZatPoint(sp));
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector.

View file

@ -181,6 +181,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t::splane &p, s
("texture", p.Texture, def->Texture)
("texz", p.TexZ, def->TexZ)
("alpha", p.alpha, def->alpha)
("glowcolor", p.GlowColor, def->GlowColor)
("glowheight", p.GlowHeight, def->GlowHeight)
.EndObject();
}
return arc;

View file

@ -1510,9 +1510,10 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
else // [RH] Translate to new sector special
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
tagManager.AddSectorTag(i, LittleShort(ms->tag));
ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98
ss->render_thinglist = NULL;
ss->thinglist = nullptr;
ss->touching_thinglist = nullptr; // phares 3/14/98
ss->render_thinglist = nullptr;
ss->touching_renderthings = nullptr;
ss->seqType = defSeqType;
ss->SeqName = NAME_None;
ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
@ -4080,6 +4081,13 @@ void P_SetupLevel (const char *lumpname, int position)
// set up world state
P_SpawnSpecials ();
// disable reflective planes on sloped sectors.
for (auto i = 0; i < numsectors; i++)
{
if (sectors[i].floorplane.isSlope()) sectors[i].reflect[sector_t::floor] = 0;
if (sectors[i].ceilingplane.isSlope()) sectors[i].reflect[sector_t::ceiling] = 0;
}
// This must be done BEFORE the PolyObj Spawn!!!
Renderer->PreprocessLevel();

View file

@ -516,6 +516,7 @@ public:
EFloor m_Type;
int m_Crush;
bool m_Hexencrush;
bool m_Instant;
int m_Direction;
secspecial_t m_NewSpecial;
FTextureID m_Texture;

View file

@ -1279,8 +1279,9 @@ public:
void ParseSector(sector_t *sec, int index)
{
int lightcolor = -1;
int fadecolor = -1;
PalEntry lightcolor = -1;
PalEntry fadecolor = -1;
int fogdensity = -1;
int desaturation = -1;
int fplaneflags = 0, cplaneflags = 0;
double fp[4] = { 0 }, cp[4] = { 0 };
@ -1294,9 +1295,10 @@ public:
sec->SetYScale(sector_t::ceiling, 1.);
sec->SetAlpha(sector_t::floor, 1.);
sec->SetAlpha(sector_t::ceiling, 1.);
sec->thinglist = NULL;
sec->touching_thinglist = NULL; // phares 3/14/98
sec->render_thinglist = NULL;
sec->thinglist = nullptr;
sec->touching_thinglist = nullptr; // phares 3/14/98
sec->render_thinglist = nullptr;
sec->touching_renderthings = nullptr;
sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1;
sec->nextsec = -1; //jff 2/26/98 add fields to support locking out
sec->prevsec = -1; // stair retriggering until build completes
@ -1460,6 +1462,10 @@ public:
desaturation = int(255*CheckFloat(key));
continue;
case NAME_fogdensity:
fogdensity = clamp(CheckInt(key), 0, 511);
break;
case NAME_Silent:
Flag(sec->Flags, SECF_SILENT, key);
continue;
@ -1562,16 +1568,20 @@ public:
sec->terrainnum[sector_t::ceiling] = P_FindTerrain(CheckString(key));
break;
case NAME_floor_reflect:
sec->reflect[sector_t::floor] = (float)CheckFloat(key);
break;
case NAME_ceiling_reflect:
sec->reflect[sector_t::ceiling] = (float)CheckFloat(key);
break;
case NAME_MoreIds:
// delay parsing of the tag string until parsing of the sector is complete
// This ensures that the ID is always the first tag in the list.
tagstring = CheckString(key);
break;
case NAME_portal_ceil_alpha:
sec->planes[sector_t::ceiling].alpha = CheckFloat(key);
break;
case NAME_portal_ceil_blocksound:
Flag(sec->planes[sector_t::ceiling].Flags, PLANEF_BLOCKSOUND, key);
break;
@ -1593,10 +1603,6 @@ public:
else if (!stricmp(CheckString(key), "additive")) sec->planes[sector_t::ceiling].Flags |= PLANEF_ADDITIVE;
break;
case NAME_portal_floor_alpha:
sec->planes[sector_t::floor].alpha = CheckFloat(key);
break;
case NAME_portal_floor_blocksound:
Flag(sec->planes[sector_t::floor].Flags, PLANEF_BLOCKSOUND, key);
break;
@ -1673,7 +1679,7 @@ public:
sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]);
}
if (lightcolor == -1 && fadecolor == -1 && desaturation == -1)
if (lightcolor == -1 && fadecolor == -1 && desaturation == -1 && fogdensity == -1)
{
// [RH] Sectors default to white light with the default fade.
// If they are outside (have a sky ceiling), they use the outside fog.
@ -1701,6 +1707,8 @@ public:
fadecolor = level.fadeto;
}
if (desaturation == -1) desaturation = NormalLight.Desaturate;
if (fogdensity != -1) fadecolor.a = fogdensity / 2;
else fadecolor.a = 0;
sec->ColorMap = GetSpecialLights (lightcolor, fadecolor, desaturation);
}

View file

@ -2940,7 +2940,8 @@ void P_UnPredictPlayer ()
// could cause it to change during prediction.
player->camera = savedcamera;
act->UnlinkFromWorld();
FLinkContext ctx;
act->UnlinkFromWorld(&ctx);
memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act));
// The blockmap ordering needs to remain unchanged, too.
@ -2969,7 +2970,7 @@ void P_UnPredictPlayer ()
}
// Destroy old refrences
msecnode_t *node = sector_list;
msecnode_t *node = ctx.sector_list;
while (node)
{
node->m_thing = NULL;
@ -2977,22 +2978,23 @@ void P_UnPredictPlayer ()
}
// Make the sector_list match the player's touching_sectorlist before it got predicted.
P_DelSeclist(sector_list);
sector_list = NULL;
P_DelSeclist(ctx.sector_list, &sector_t::touching_thinglist);
ctx.sector_list = NULL;
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
{
sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist);
ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist);
}
act->touching_sectorlist = sector_list; // Attach to thing
sector_list = NULL; // clear for next time
act->touching_sectorlist = ctx.sector_list; // Attach to thing
ctx.sector_list = NULL; // clear for next time
node = sector_list;
// Huh???
node = ctx.sector_list;
while (node)
{
if (node->m_thing == NULL)
{
if (node == sector_list)
sector_list = node->m_tnext;
if (node == ctx.sector_list)
ctx.sector_list = node->m_tnext;
node = P_DelSecnode(node, &sector_t::touching_thinglist);
}
else

View file

@ -1138,8 +1138,9 @@ void P_CreateLinkedPortals()
P_CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check);
if (check.Size() > 0)
{
actor->UnlinkFromWorld();
actor->LinkToWorld();
FLinkContext ctx;
actor->UnlinkFromWorld(&ctx);
actor->LinkToWorld(&ctx);
}
}
}

View file

@ -41,10 +41,6 @@
#include <new>
#include <sys/param.h>
#include <locale.h>
#if defined(__MACH__) && !defined(NOASM)
#include <sys/types.h>
#include <sys/mman.h>
#endif
#include "doomerrors.h"
#include "m_argv.h"
@ -185,46 +181,6 @@ static int DoomSpecificInfo (char *buffer, char *end)
return p;
}
#if defined(__MACH__) && !defined(NOASM)
// NASM won't let us create custom sections for Mach-O. Whether that's a limitation of NASM
// or of Mach-O, I don't know, but since we're using NASM for the assembly, it doesn't much
// matter.
extern "C"
{
extern void *rtext_a_start, *rtext_a_end;
extern void *rtext_tmap_start, *rtext_tmap_end;
extern void *rtext_tmap2_start, *rtext_tmap2_end;
extern void *rtext_tmap3_start, *rtext_tmap3_end;
};
static void unprotect_pages(long pagesize, void *start, void *end)
{
char *page = (char *)((intptr_t)start & ~(pagesize - 1));
size_t len = (char *)end - (char *)start;
if (mprotect(page, len, PROT_READ|PROT_WRITE|PROT_EXEC) != 0)
{
fprintf(stderr, "mprotect failed\n");
exit(1);
}
}
static void unprotect_rtext()
{
static void *const pages[] =
{
rtext_a_start, rtext_a_end,
rtext_tmap_start, rtext_tmap_end,
rtext_tmap2_start, rtext_tmap2_end,
rtext_tmap3_start, rtext_tmap3_end
};
long pagesize = sysconf(_SC_PAGESIZE);
for (void *const *p = pages; p < &pages[countof(pages)]; p += 2)
{
unprotect_pages(pagesize, p[0], p[1]);
}
}
#endif
void I_StartupJoysticks();
void I_ShutdownJoysticks();
@ -243,10 +199,6 @@ int main (int argc, char **argv)
seteuid (getuid ());
std::set_new_handler (NewFailure);
#if defined(__MACH__) && !defined(NOASM)
unprotect_rtext();
#endif
// Set LC_NUMERIC environment variable in case some library decides to
// clear the setlocale call at least this will be correct.
// Note that the LANG environment variable is overridden by LC_*

View file

@ -17,6 +17,7 @@ struct FDynamicColormap
void ChangeFade (PalEntry fadecolor);
void ChangeColor (PalEntry lightcolor, int desaturate);
void ChangeColorFade (PalEntry lightcolor, PalEntry fadecolor);
void ChangeFogDensity(int newdensity);
void BuildLights ();
static void RebuildAllLights();

View file

@ -24,6 +24,7 @@
#ifndef __R_DEFS_H__
#define __R_DEFS_H__
#include <forward_list>
#include "doomdef.h"
#include "templates.h"
#include "memarena.h"
@ -627,9 +628,9 @@ struct sector_t
// Member functions
private:
bool MoveAttached(int crush, double move, int floorOrCeiling, bool resetfailed);
bool MoveAttached(int crush, double move, int floorOrCeiling, bool resetfailed, bool instant = false);
public:
EMoveResult MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush);
EMoveResult MoveFloor(double speed, double dest, int crush, int direction, bool hexencrush, bool instant = false);
EMoveResult MoveCeiling(double speed, double dest, int crush, int direction, bool hexencrush);
inline EMoveResult MoveFloor(double speed, double dest, int direction)
@ -687,8 +688,10 @@ public:
int Flags;
int Light;
double alpha;
FTextureID Texture;
double TexZ;
PalEntry GlowColor;
float GlowHeight;
FTextureID Texture;
};
@ -1029,11 +1032,11 @@ public:
};
TObjPtr<DInterpolation> interpolations[4];
int prevsec; // -1 or number of sector for previous step
int nextsec; // -1 or number of next step sector
BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1
// jff 2/26/98 lockout machinery for stairbuilding
SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally
int prevsec; // -1 or number of sector for previous step
int nextsec; // -1 or number of next step sector
short linecount;
struct line_t **lines; // [linecount] size
@ -1049,6 +1052,7 @@ public:
// thinglist is a subset of touching_thinglist
struct msecnode_t *touching_thinglist; // phares 3/14/98
struct msecnode_t *render_thinglist; // for cross-portal rendering.
struct msecnode_t *touching_renderthings; // this is used to allow wide things to be rendered not only from their main sector.
double gravity; // [RH] Sector gravity (1.0 is normal)
FNameNoInit damagetype; // [RH] Means-of-death for applied damage

View file

@ -107,6 +107,7 @@ int viewwindowx;
int viewwindowy;
DVector3 ViewPos;
DVector3 ViewActorPos; // the actual position of the viewing actor, without interpolation and quake offsets.
DAngle ViewAngle;
DAngle ViewPitch;
DAngle ViewRoll;
@ -744,10 +745,11 @@ void R_SetupFrame (AActor *actor)
iview->Old = iview->New;
r_NoInterpolate = true;
}
ViewActorPos = campos;
}
else
{
iview->New.Pos = { camera->Pos().XY(), camera->player ? camera->player->viewz : camera->Z() + camera->GetCameraHeight() };
ViewActorPos = iview->New.Pos = { camera->Pos().XY(), camera->player ? camera->player->viewz : camera->Z() + camera->GetCameraHeight() };
viewsector = camera->Sector;
r_showviewer = false;
}

View file

@ -15,6 +15,7 @@ class FSerializer;
extern DCanvas *RenderTarget;
extern DVector3 ViewPos;
extern DVector3 ViewActorPos;
extern DAngle ViewAngle;
extern DAngle ViewPitch;
extern DAngle ViewRoll;

View file

@ -918,6 +918,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
// the referenced sound so some additional checks are required
int near_limit = sfx->NearLimit;
float limit_range = sfx->LimitRange;
auto pitchmask = sfx->PitchMask;
rolloff = &sfx->Rolloff;
// Resolve player sounds, random sounds, and aliases
@ -1082,9 +1083,9 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
}
// Vary the sfx pitches.
if (sfx->PitchMask != 0)
if (pitchmask != 0)
{
pitch = NORM_PITCH - (M_Random() & sfx->PitchMask) + (M_Random() & sfx->PitchMask);
pitch = NORM_PITCH - (M_Random() & pitchmask) + (M_Random() & pitchmask);
}
else
{

View file

@ -7493,7 +7493,7 @@ isresolved:
else
{
// Todo: If this is a qualified call to a parent class function, let it through (but this needs to disable virtual calls later.)
ScriptPosition.Message(MSG_ERROR, "Qualified member call to parent class not yet implemented\n", cls->TypeName.GetChars(), MethodName.GetChars());
ScriptPosition.Message(MSG_ERROR, "Qualified member call to parent class %s::%s is not yet implemented\n", cls->TypeName.GetChars(), MethodName.GetChars());
delete this;
return nullptr;
}
@ -7897,7 +7897,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
// For a reference argument the types must match 100%.
if (type != ArgList[i]->ValueType)
{
ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument", Function->SymbolName.GetChars());
ScriptPosition.Message(MSG_ERROR, "Type mismatch in reference argument %s", Function->SymbolName.GetChars());
x = nullptr;
}
else
@ -8346,7 +8346,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx)
{
// this is the ugly case. We do not know what we have and cannot do proper type casting.
// For now error out and let this case require explicit handling on the user side.
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type", static_cast<FxConstant *>(Self)->GetValue().GetString().GetChars());
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type, but got %s", static_cast<FxConstant *>(Self)->GetValue().GetString().GetChars());
delete this;
return nullptr;
}
@ -9511,7 +9511,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
/* lax */
// Since this happens in released WADs it must pass without a terminal error... :(
ScriptPosition.Message(MSG_OPTERROR,
"Unknown class name '%s'",
"Unknown class name '%s' of type '%s'",
clsname.GetChars(), desttype->TypeName.GetChars());
}
else

View file

@ -272,7 +272,7 @@ static void CheckForUnsafeStates(PClassActor *obj)
// If an unsafe function (i.e. one that accesses user variables) is being detected, print a warning once and remove the bogus function. We may not call it because that would inevitably crash.
auto owner = FState::StaticFindStateOwner(state);
GetStateSource(state).Message(MSG_ERROR, TEXTCOLOR_RED "Unsafe state call in state %s.%d which accesses user variables, reached by %s.%s.\n",
owner->TypeName.GetChars(), state - owner->OwnedStates, obj->TypeName.GetChars(), FName(*test).GetChars());
owner->TypeName.GetChars(), int(state - owner->OwnedStates), obj->TypeName.GetChars(), FName(*test).GetChars());
}
state = state->NextState;
}
@ -425,6 +425,15 @@ void LoadActors()
CheckForUnsafeStates(ti);
}
// ensure that all actor bouncers have PASSMOBJ set.
auto defaults = GetDefaultByType(ti);
if (defaults->BounceFlags & (BOUNCE_Actors | BOUNCE_AllActors))
{
// PASSMOBJ is irrelevant for normal missiles, but not for bouncers.
defaults->flags2 |= MF2_PASSMOBJ;
}
}
if (FScriptPosition::ErrorCounter > 0)
{

View file

@ -216,9 +216,10 @@ bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror)
// If these 2 flags get changed we need to update the blockmap and sector links.
bool linkchange = flagp == &actor->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
if (linkchange) actor->UnlinkFromWorld();
FLinkContext ctx;
if (linkchange) actor->UnlinkFromWorld(&ctx);
ModActorFlag(actor, fd, set);
if (linkchange) actor->LinkToWorld();
if (linkchange) actor->LinkToWorld(&ctx);
}
if (actor->CountsAsKill() && actor->health > 0) ++level.total_monsters;
@ -525,7 +526,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
if (info->Size != actorclass->Size)
{
bag.ScriptPosition.Message(MSG_OPTERROR,
"'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored.", info->TypeName.GetChars());
"'skip_super' is only allowed in subclasses of AActor with no additional fields and will be ignored in type %s.", info->TypeName.GetChars());
return;
}
if (bag.StateSet)
@ -713,6 +714,15 @@ DEFINE_PROPERTY(radius, F, Actor)
defaults->radius = id;
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(renderradius, F, Actor)
{
PROP_DOUBLE_PARM(id, 0);
defaults->renderradius = id;
}
//==========================================================================
//
//==========================================================================
@ -1206,11 +1216,6 @@ DEFINE_PROPERTY(bouncetype, S, Actor)
}
defaults->BounceFlags &= ~(BOUNCE_TypeMask | BOUNCE_UseSeeSound);
defaults->BounceFlags |= flags[match];
if (defaults->BounceFlags & (BOUNCE_Actors | BOUNCE_AllActors))
{
// PASSMOBJ is irrelevant for normal missiles, but not for bouncers.
defaults->flags2 |= MF2_PASSMOBJ;
}
}
//==========================================================================

View file

@ -21,27 +21,35 @@ typedef VM_UBYTE VM_ATAG;
#define VM_EPSILON (1/65536.0)
#ifdef __BIG_ENDIAN__
#define VM_DEFINE_OP2(TYPE, ARG1, ARG2) TYPE ARG2, ARG1
#define VM_DEFINE_OP4(TYPE, ARG1, ARG2, ARG3, ARG4) TYPE ARG4, ARG3, ARG2, ARG1
#else // little endian
#define VM_DEFINE_OP2(TYPE, ARG1, ARG2) TYPE ARG1, ARG2
#define VM_DEFINE_OP4(TYPE, ARG1, ARG2, ARG3, ARG4) TYPE ARG1, ARG2, ARG3, ARG4
#endif // __BIG_ENDIAN__
union VMOP
{
struct
{
VM_UBYTE op, a, b, c;
VM_DEFINE_OP4(VM_UBYTE, op, a, b, c);
};
struct
{
VM_SBYTE pad0, as, bs, cs;
VM_DEFINE_OP4(VM_SBYTE, pad0, as, bs, cs);
};
struct
{
VM_SWORD pad1:8, i24:24;
VM_DEFINE_OP2(VM_SWORD, pad1:8, i24:24);
};
struct
{
VM_SWORD pad2:16, i16:16;
VM_DEFINE_OP2(VM_SWORD, pad2:16, i16:16);
};
struct
{
VM_UHALF pad3, i16u;
VM_DEFINE_OP2(VM_UHALF, pad3, i16u);
};
VM_UWORD word;
@ -56,6 +64,9 @@ union VMOP
// sar eax,10h
};
#undef VM_DEFINE_OP4
#undef VM_DEFINE_OP2
enum
{
#include "vmops.h"

View file

@ -1323,7 +1323,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
}
else if (hasnativechildren)
{
Error(field, "Cannot add field %s to %s. %s has native children which means it size may not change.", type->TypeName.GetChars(), fd->FieldSize, FName(name->Name).GetChars());
Error(field, "Cannot add field %s to %s. %s has native children which means it size may not change.", FName(name->Name).GetChars(), type->TypeName.GetChars(), type->TypeName.GetChars());
}
else
{

View file

@ -227,7 +227,12 @@ void MusInfo::Start(bool loop, float rel_vol, int subsong)
{
if (nomusic) return;
if (rel_vol > 0.f) saved_relative_volume = relative_volume = rel_vol;
if (rel_vol > 0.f)
{
float factor = relative_volume / saved_relative_volume;
saved_relative_volume = rel_vol;
relative_volume = saved_relative_volume * factor;
}
Stop ();
Play (loop, subsong);
m_NotStartedYet = false;
@ -672,6 +677,14 @@ void I_SetMusicVolume (float factor)
snd_musicvolume.Callback();
}
DEFINE_ACTION_FUNCTION(DObject, SetMusicVolume)
{
PARAM_PROLOGUE;
PARAM_FLOAT(vol);
I_SetMusicVolume((float)vol);
return 0;
}
//==========================================================================
//
// test a relative music volume

View file

@ -315,6 +315,7 @@ public:
float shaderspeed;
int mIsTransparent:2;
bool bGlowing:1; // Texture glows
bool bAutoGlowing : 1; // Glow info is determined from texture image.
bool bFullbright:1; // always draw fullbright
bool bSkybox:1; // This is a skybox
char bBrightmapChecked:1; // Set to 1 if brightmap has been checked

View file

@ -38,6 +38,8 @@
#include "zscript/shared/fastprojectile.txt"
#include "zscript/shared/dynlights.txt"
#include "zscript/compatibility.txt"
#include "zscript/doom/doomplayer.txt"
#include "zscript/doom/possessed.txt"
#include "zscript/doom/doomimp.txt"

View file

@ -45,6 +45,7 @@ class Actor : Thinker native
native TextureID ceilingpic;
native double Height;
native readonly double Radius;
native readonly double RenderRadius;
native double projectilepassheight;
native int tics;
native readonly State CurState;
@ -201,6 +202,7 @@ class Actor : Thinker native
Health DEFAULT_HEALTH;
Reactiontime 8;
Radius 20;
RenderRadius 0;
Height 16;
Mass 100;
RenderStyle 'Normal';
@ -691,7 +693,7 @@ class Actor : Thinker native
deprecated native void A_StopSoundEx(name slot);
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
native action state A_Jump(int chance, statelabel label, ...);
native void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
native void A_SpawnProjectile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
native void A_CustomBulletAttack(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, double maxdiff = 0, class<Actor> pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class<Actor> spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
native bool A_SetInventory(class<Inventory> itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false);

View file

@ -12,6 +12,9 @@ class Object native
native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false);
native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable.
native static uint BAM(double angle);
native static void SetMusicVolume(float vol);
native Name GetClassName();
/*virtual*/ native void Destroy();
}

View file

@ -77,7 +77,7 @@ class ZorchPropulsor : RocketLauncher
{
Fire:
MISG B 8 A_GunFlash;
MISG B 12 A_FireCustomMissile("PropulsorMissile");
MISG B 12 A_FireProjectile("PropulsorMissile");
MISG B 0 A_ReFire;
Goto Ready;
}
@ -107,7 +107,7 @@ class PhasingZorcher : PlasmaRifle
{
Fire:
PLSG A 0 A_GunFlash;
PLSG A 3 A_FireCustomMissile("PhaseZorchMissile");
PLSG A 3 A_FireProjectile("PhaseZorchMissile");
PLSG B 20 A_ReFire;
Goto Ready;
Flash:
@ -143,7 +143,7 @@ class LAZDevice : BFG9000
Fire:
BFGG A 20 A_BFGsound;
BFGG B 10 A_GunFlash;
BFGG B 10 A_FireCustomMissile("LAZBall");
BFGG B 10 A_FireProjectile("LAZBall");
BFGG B 20 A_ReFire;
Goto Ready;
}

View file

@ -0,0 +1,18 @@
// This file contains compatibility wrappers for DECORATE functions with bad parameters.
extend class Actor
{
deprecated void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET)
{
A_SpawnProjectile(missiletype, spawnheight, spawnofs_xy, angle, flags|CMF_BADPITCH, pitch, ptr);
}
}
extend class StateProvider
{
deprecated action void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0)
{
A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch);
}
}

View file

@ -45,7 +45,7 @@ enum EBFGSprayFlags
BFGF_MISSILEORIGIN = 2,
};
// Flags for A_CustomMissile
// Flags for A_SpawnProjectile
enum ECustomMissileFlags
{
CMF_AIMOFFSET = 1,
@ -56,6 +56,7 @@ enum ECustomMissileFlags
CMF_OFFSETPITCH = 32,
CMF_SAVEPITCH = 64,
CMF_ABSOLUTEANGLE = 128,
CMF_BADPITCH = 256, // for compatibility handling only - avoid!
};
// Flags for A_CustomBulletAttack

View file

@ -125,25 +125,26 @@ extend class Actor
void A_VileAttack(sound snd = "vile/stop", int initialdmg = 20, int blastdmg = 70, int blastradius = 70, double thrust = 1.0, name damagetype = "Fire", int flags = 0)
{
if (target)
Actor targ = target;
if (targ)
{
A_FaceTarget();
if (!CheckSight(target, 0)) return;
if (!CheckSight(targ, 0)) return;
A_PlaySound(snd, CHAN_WEAPON);
int newdam = target.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none');
int newdam = targ.DamageMobj (self, self, initialdmg, (flags & VAF_DMGTYPEAPPLYTODIRECT)? damagetype : 'none');
TraceBleed (newdam > 0 ? newdam : initialdmg, target);
TraceBleed (newdam > 0 ? newdam : initialdmg, targ);
Actor fire = tracer;
if (fire)
{
// move the fire between the vile and the player
fire.SetOrigin(target.Vec3Angle(-24., angle, 0), true);
fire.SetOrigin(targ.Vec3Angle(-24., angle, 0), true);
fire.A_Explode(blastdmg, blastradius, XF_NOSPLASH, false, 0, 0, 0, "BulletPuff", damagetype);
}
if (!target.bDontThrust)
if (!targ.bDontThrust)
{
target.Vel.z = thrust * 1000 / max(1, target.Mass);
targ.Vel.z = thrust * 1000 / max(1, targ.Mass);
}
}
}

View file

@ -28,9 +28,9 @@ class Snake : Actor
Loop;
Missile:
SNKE FF 5 A_FaceTarget;
SNKE FFF 4 A_CustomMissile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD);
SNKE FFF 4 A_SpawnProjectile("SnakeProjA", 32, 0, 0, CMF_CHECKTARGETDEAD);
SNKE FFF 5 A_FaceTarget;
SNKE F 4 A_CustomMissile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD);
SNKE F 4 A_SpawnProjectile("SnakeProjB", 32, 0, 0, CMF_CHECKTARGETDEAD);
Goto See;
Pain:
SNKE E 3;

View file

@ -87,7 +87,7 @@ class BlasterPowered : Blaster
Fire:
BLSR BC 0;
Hold:
BLSR D 3 A_FireCustomMissile("BlasterFX1");
BLSR D 3 A_FireProjectile("BlasterFX1");
BLSR CB 4;
BLSR A 0 A_ReFire;
Goto Ready;

View file

@ -112,9 +112,9 @@ class CentaurLeader : Centaur
{
Missile:
CENT E 10 A_FaceTarget;
CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET);
CENT F 8 Bright A_SpawnProjectile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET);
CENT E 10 A_FaceTarget;
CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET);
CENT F 8 Bright A_SpawnProjectile("CentaurFX", 45, 0, 0, CMF_AIMOFFSET);
Goto See;
}
}

View file

@ -44,7 +44,7 @@ class Demon1 : Actor
Missile:
DEMN E 5 A_FaceTarget;
DEMN F 6 A_FaceTarget;
DEMN G 5 A_CustomMissile("Demon1FX1", 62, 0);
DEMN G 5 A_SpawnProjectile("Demon1FX1", 62, 0);
Goto See;
Death:
DEMN HI 6;
@ -250,7 +250,7 @@ class Demon2 : Demon1
Missile:
DEM2 E 5 A_FaceTarget;
DEM2 F 6 A_FaceTarget;
DEM2 G 5 A_CustomMissile("Demon2FX1", 62, 0);
DEM2 G 5 A_SpawnProjectile("Demon2FX1", 62, 0);
Goto See;
Death:
DEM2 HI 6;

View file

@ -23,7 +23,7 @@ class MWeapWand : MageWeapon
Loop;
Fire:
MWND A 6;
MWND B 6 Bright Offset (0, 48) A_FireCustomMissile ("MageWandMissile");
MWND B 6 Bright Offset (0, 48) A_FireProjectile ("MageWandMissile");
MWND A 3 Offset (0, 40);
MWND A 3 Offset (0, 36) A_ReFire;
Goto Ready;

View file

@ -300,7 +300,7 @@ class SerpentLeader : Serpent
States
{
Missile:
SSPT N 5 A_CustomMissile("SerpentFX", 32, 0);
SSPT N 5 A_SpawnProjectile("SerpentFX", 32, 0);
Goto Dive;
}
}

View file

@ -47,7 +47,7 @@ class Wraith : Actor
Missile:
WRTH E 6 A_FaceTarget;
WRTH F 6;
WRTH G 6 A_CustomMissile("WraithFX1");
WRTH G 6 A_SpawnProjectile("WraithFX1");
Goto See;
Death:
WRTH I 4;

View file

@ -49,7 +49,7 @@ class ArtiEgg : CustomInventory
Use:
TNT1 A 0
{
for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("EggFX", i, 0, 0, 0, 1);
for (double i = -15; i <= 15; i += 7.5) A_FireProjectile("EggFX", i, false, 0, 0, FPF_AIMATANGLE);
}
Stop;
}
@ -104,7 +104,7 @@ class ArtiPork : CustomInventory
Use:
TNT1 A 0
{
for (double i = -15; i <= 15; i += 7.5) A_FireCustomMissile("PorkFX", i, 0, 0, 0, 1);
for (double i = -15; i <= 15; i += 7.5) A_FireProjectile("PorkFX", i, false, 0, 0, FPF_AIMATANGLE);
}
Stop;
}

View file

@ -85,6 +85,7 @@ class InvisibleBridge : Actor native
{
RenderStyle "None";
Radius 32;
RenderRadius -1;
Height 4;
+SOLID
+NOGRAVITY

View file

@ -5,6 +5,7 @@ class DynamicLight : Actor native
Height 0;
Radius 0.1;
FloatBobPhase 0;
RenderRadius -1;
+NOBLOCKMAP
+NOGRAVITY
+FIXMAPTHINGPOS

View file

@ -84,7 +84,7 @@ class StateProvider : Inventory native
action native state A_JumpIfNoAmmo(statelabel label);
action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
action native void A_FireBullets(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, double range = 0, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
action native void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0);
action native void A_FireProjectile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0);
action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class<Actor> pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class<Actor> spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
action native void A_WeaponReady(int flags = 0);
action native void A_Lower();

View file

@ -202,7 +202,7 @@ class AlienSpectre2 : AlienSpectre1
{
Missile:
ALN1 F 4 A_FaceTarget;
ALN1 I 4 A_CustomMissile("SpectralLightningH3", 32, 0);
ALN1 I 4 A_SpawnProjectile("SpectralLightningH3", 32, 0);
ALN1 E 4;
Goto See+10;
}
@ -267,7 +267,7 @@ class AlienSpectre4 : AlienSpectre1
{
Missile:
ALN1 F 4 A_FaceTarget;
ALN1 I 4 A_CustomMissile("SpectralLightningBigV2", 32, 0);
ALN1 I 4 A_SpawnProjectile("SpectralLightningBigV2", 32, 0);
ALN1 E 4;
Goto See+10;
}
@ -289,7 +289,7 @@ class AlienSpectre5 : AlienSpectre1
{
Missile:
ALN1 F 4 A_FaceTarget;
ALN1 I 4 A_CustomMissile("SpectralLightningBigBall2", 32, 0);
ALN1 I 4 A_SpawnProjectile("SpectralLightningBigBall2", 32, 0);
ALN1 E 4;
Goto See+10;
}

View file

@ -265,7 +265,7 @@ class EntitySecond : SpectralMonster
Goto See+1;
Missile:
MNAL W 4 Bright A_FaceTarget;
MNAL U 4 Bright A_CustomMissile("SpectralLightningH3",32,0);
MNAL U 4 Bright A_SpawnProjectile("SpectralLightningH3",32,0);
MNAL V 4 Bright A_SentinelBob;
Goto See+4;
Pain:

View file

@ -55,7 +55,7 @@ class Loremaster : Actor
Goto See;
Missile:
PRST E 4 A_FaceTarget;
PRST F 4 A_CustomMissile("LoreShot", 32, 0);
PRST F 4 A_SpawnProjectile("LoreShot", 32, 0);
PRST E 4 A_SentinelBob;
Goto See;
Death:

View file

@ -38,7 +38,7 @@ class StrifeBishop : Actor
Loop;
Missile:
MLDR E 3 A_FaceTarget;
MLDR F 2 Bright A_CustomMissile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET);
MLDR F 2 Bright A_SpawnProjectile("BishopMissile", 64, 0, 0, CMF_AIMOFFSET);
Goto See;
Pain:
MLDR D 1 A_Pain;

View file

@ -56,7 +56,7 @@ class PunchDagger : StrifeWeapon
// turn to face target
if (t.linetarget)
{
S_Sound (t.linetarget.bNoBlood ? sound("misc/metalhit") : sound("misc/meathit"), CHAN_WEAPON);
A_PlaySound (t.linetarget.bNoBlood ? sound("misc/metalhit") : sound("misc/meathit"), CHAN_WEAPON);
angle = t.angleFromSource;
bJustAttacked = true;
t.linetarget.DaggerAlert (self);

View file

@ -1,6 +1,69 @@
ChangeLog file for zlib
Changes in 1.2.8 (28 Apr 2013)
- Update contrib/minizip/iowin32.c for Windows RT [Vollant]
- Do not force Z_CONST for C++
- Clean up contrib/vstudio [Ro§]
- Correct spelling error in zlib.h
- Fix mixed line endings in contrib/vstudio
Changes in 1.2.7.3 (13 Apr 2013)
- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc
Changes in 1.2.7.2 (13 Apr 2013)
- Change check for a four-byte type back to hexadecimal
- Fix typo in win32/Makefile.msc
- Add casts in gzwrite.c for pointer differences
Changes in 1.2.7.1 (24 Mar 2013)
- Replace use of unsafe string functions with snprintf if available
- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink]
- Fix gzgetc undefine when Z_PREFIX set [Turk]
- Eliminate use of mktemp in Makefile (not always available)
- Fix bug in 'F' mode for gzopen()
- Add inflateGetDictionary() function
- Correct comment in deflate.h
- Use _snprintf for snprintf in Microsoft C
- On Darwin, only use /usr/bin/libtool if libtool is not Apple
- Delete "--version" file if created by "ar --version" [Richard G.]
- Fix configure check for veracity of compiler error return codes
- Fix CMake compilation of static lib for MSVC2010 x64
- Remove unused variable in infback9.c
- Fix argument checks in gzlog_compress() and gzlog_write()
- Clean up the usage of z_const and respect const usage within zlib
- Clean up examples/gzlog.[ch] comparisons of different types
- Avoid shift equal to bits in type (caused endless loop)
- Fix unintialized value bug in gzputc() introduced by const patches
- Fix memory allocation error in examples/zran.c [Nor]
- Fix bug where gzopen(), gzclose() would write an empty file
- Fix bug in gzclose() when gzwrite() runs out of memory
- Check for input buffer malloc failure in examples/gzappend.c
- Add note to contrib/blast to use binary mode in stdio
- Fix comparisons of differently signed integers in contrib/blast
- Check for invalid code length codes in contrib/puff
- Fix serious but very rare decompression bug in inftrees.c
- Update inflateBack() comments, since inflate() can be faster
- Use underscored I/O function names for WINAPI_FAMILY
- Add _tr_flush_bits to the external symbols prefixed by --zprefix
- Add contrib/vstudio/vc10 pre-build step for static only
- Quote --version-script argument in CMakeLists.txt
- Don't specify --version-script on Apple platforms in CMakeLists.txt
- Fix casting error in contrib/testzlib/testzlib.c
- Fix types in contrib/minizip to match result of get_crc_table()
- Simplify contrib/vstudio/vc10 with 'd' suffix
- Add TOP support to win32/Makefile.msc
- Suport i686 and amd64 assembler builds in CMakeLists.txt
- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
- Add vc11 and vc12 build files to contrib/vstudio
- Add gzvprintf() as an undocumented function in zlib
- Fix configure for Sun shell
- Remove runtime check in configure for four-byte integer type
- Add casts and consts to ease user conversion to C++
- Add man pages for minizip and miniunzip
- In Makefile uninstall, don't rm if preceding cd fails
- Do not return Z_BUF_ERROR if deflateParam() has nothing to write
Changes in 1.2.7 (2 May 2012)
- Replace use of memmove() with a simple copy for portability
- Test for existence of strerror

View file

@ -1,22 +1,22 @@
ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.5 is a general purpose data compression library. All the code is
zlib 1.2.8 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
and rfc1952.txt (gzip format).
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
rfc1952 (gzip format).
All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
of the library is given in the file example.c which also tests that the library
is working correctly. Another example is given in the file minigzip.c. The
compression library itself is composed of all source files except example.c and
minigzip.c.
of the library is given in the file test/example.c which also tests that
the library is working correctly. Another example is given in the file
test/minigzip.c. The compression library itself is composed of all source
files in the root directory.
To compile all files and run the test program, follow the instructions given at
the top of Makefile.in. In short "./configure; make test", and if that goes
well, "make install" should work for most flavors of Unix. For Windows, use one
of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
well, "make install" should work for most flavors of Unix. For Windows, use
one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
make_vms.com.
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
@ -31,7 +31,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available at
http://marknelson.us/1997/01/01/zlib-engine/ .
The changes made in version 1.2.5 are documented in the file ChangeLog.
The changes made in version 1.2.8 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory contrib/ .
@ -44,7 +44,7 @@ http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
available in Python 1.5 and later versions, see
http://www.python.org/doc/lib/module-zlib.html .
http://docs.python.org/library/zlib.html .
zlib is built into tcl: http://wiki.tcl.tk/4610 .
@ -84,7 +84,7 @@ Acknowledgments:
Copyright notice:
(C) 1995-2010 Jean-loup Gailly and Mark Adler
(C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

Some files were not shown because too many files have changed in this diff Show more