mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- at least get the terms being used right. Of course it's not EDF (which would way beyond the scope of what's intended here) but only Extradata, that's being supported.
(For EDF an external converter would make more sense.)
This commit is contained in:
parent
7c8d48bbfc
commit
9e33599536
7 changed files with 88 additions and 76 deletions
|
@ -944,7 +944,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
||||||
doomstat.cpp
|
doomstat.cpp
|
||||||
dsectoreffect.cpp
|
dsectoreffect.cpp
|
||||||
dthinker.cpp
|
dthinker.cpp
|
||||||
edf.cpp
|
edata.cpp
|
||||||
f_wipe.cpp
|
f_wipe.cpp
|
||||||
farchive.cpp
|
farchive.cpp
|
||||||
files.cpp
|
files.cpp
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
** edf.cpp
|
** edata.cpp
|
||||||
** Parses Eternity EDF lumps
|
** Parses Eternity Extradata lumps
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 2015 Christoph Oelckers
|
** Copyright 2015 Christoph Oelckers
|
||||||
|
@ -51,43 +51,43 @@
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
|
|
||||||
|
|
||||||
struct FEdfOptions : public FOptionalMapinfoData
|
struct FEDOptions : public FOptionalMapinfoData
|
||||||
{
|
{
|
||||||
FEdfOptions()
|
FEDOptions()
|
||||||
{
|
{
|
||||||
identifier = "EDF";
|
identifier = "EData";
|
||||||
}
|
}
|
||||||
virtual FOptionalMapinfoData *Clone() const
|
virtual FOptionalMapinfoData *Clone() const
|
||||||
{
|
{
|
||||||
FEdfOptions *newopt = new FEdfOptions;
|
FEDOptions *newopt = new FEDOptions;
|
||||||
newopt->identifier = identifier;
|
newopt->identifier = identifier;
|
||||||
newopt->edfName = edfName;
|
newopt->EDName = EDName;
|
||||||
newopt->acsName = acsName;
|
newopt->acsName = acsName;
|
||||||
return newopt;
|
return newopt;
|
||||||
}
|
}
|
||||||
FString edfName;
|
FString EDName;
|
||||||
FString acsName;
|
FString acsName;
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_MAP_OPTION(edf, false)
|
DEFINE_MAP_OPTION(edata, false)
|
||||||
{
|
{
|
||||||
FEdfOptions *opt = info->GetOptData<FEdfOptions>("EDF");
|
FEDOptions *opt = info->GetOptData<FEDOptions>("EData");
|
||||||
|
|
||||||
parse.ParseAssign();
|
parse.ParseAssign();
|
||||||
parse.sc.MustGetString();
|
parse.sc.MustGetString();
|
||||||
opt->edfName = parse.sc.String;
|
opt->EDName = parse.sc.String;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MAP_OPTION(loadacs, false)
|
DEFINE_MAP_OPTION(loadacs, false)
|
||||||
{
|
{
|
||||||
FEdfOptions *opt = info->GetOptData<FEdfOptions>("EDF");
|
FEDOptions *opt = info->GetOptData<FEDOptions>("EData");
|
||||||
|
|
||||||
parse.ParseAssign();
|
parse.ParseAssign();
|
||||||
parse.sc.MustGetString();
|
parse.sc.MustGetString();
|
||||||
opt->acsName = parse.sc.String;
|
opt->acsName = parse.sc.String;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EDFMapthing
|
struct EDMapthing
|
||||||
{
|
{
|
||||||
int recordnum;
|
int recordnum;
|
||||||
int tid;
|
int tid;
|
||||||
|
@ -98,7 +98,7 @@ struct EDFMapthing
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EDFLinedef
|
struct EDLinedef
|
||||||
{
|
{
|
||||||
int recordnum;
|
int recordnum;
|
||||||
int special;
|
int special;
|
||||||
|
@ -112,7 +112,7 @@ struct EDFLinedef
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct EDFSector
|
struct EDSector
|
||||||
{
|
{
|
||||||
int recordnum;
|
int recordnum;
|
||||||
|
|
||||||
|
@ -146,15 +146,15 @@ struct EDFSector
|
||||||
fixed_t overlayalpha[2];
|
fixed_t overlayalpha[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static FString EDFMap;
|
static FString EDMap;
|
||||||
static TMap<int, EDFLinedef> EDFLines;
|
static TMap<int, EDLinedef> EDLines;
|
||||||
static TMap<int, EDFSector> EDFSectors;
|
static TMap<int, EDSector> EDSectors;
|
||||||
static TMap<int, EDFMapthing> EDFThings;
|
static TMap<int, EDMapthing> EDThings;
|
||||||
|
|
||||||
|
|
||||||
static void parseLinedef(FScanner &sc)
|
static void parseLinedef(FScanner &sc)
|
||||||
{
|
{
|
||||||
EDFLinedef ld;
|
EDLinedef ld;
|
||||||
bool argsset = false;
|
bool argsset = false;
|
||||||
|
|
||||||
memset(&ld, 0, sizeof(ld));
|
memset(&ld, 0, sizeof(ld));
|
||||||
|
@ -267,12 +267,12 @@ static void parseLinedef(FScanner &sc)
|
||||||
ld.flags = (ld.flags & ~(ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)) | (line.flags & (ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY));
|
ld.flags = (ld.flags & ~(ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)) | (line.flags & (ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY));
|
||||||
if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args));
|
if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args));
|
||||||
}
|
}
|
||||||
EDFLines[ld.recordnum] = ld;
|
EDLines[ld.recordnum] = ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseSector(FScanner &sc)
|
static void parseSector(FScanner &sc)
|
||||||
{
|
{
|
||||||
EDFSector sec;
|
EDSector sec;
|
||||||
|
|
||||||
memset(&sec, 0, sizeof(sec));
|
memset(&sec, 0, sizeof(sec));
|
||||||
sec.overlayalpha[sector_t::floor] = sec.overlayalpha[sector_t::ceiling] = FRACUNIT;
|
sec.overlayalpha[sector_t::floor] = sec.overlayalpha[sector_t::ceiling] = FRACUNIT;
|
||||||
|
@ -499,15 +499,15 @@ static void parseSector(FScanner &sc)
|
||||||
sc.ScriptError("Unknown property '%s'", sc.String);
|
sc.ScriptError("Unknown property '%s'", sc.String);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EDFSectors[sec.recordnum] = sec;
|
EDSectors[sec.recordnum] = sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseMapthing(FScanner &sc)
|
static void parseMapthing(FScanner &sc)
|
||||||
{
|
{
|
||||||
EDFMapthing mt;
|
EDMapthing mt;
|
||||||
|
|
||||||
memset(&mt, 0, sizeof(mt));
|
memset(&mt, 0, sizeof(mt));
|
||||||
mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // EDF uses inverse logic, like Doom.exe
|
mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // Extradata uses inverse logic, like Doom.exe
|
||||||
|
|
||||||
sc.MustGetStringName("{");
|
sc.MustGetStringName("{");
|
||||||
while (!sc.CheckString("}"))
|
while (!sc.CheckString("}"))
|
||||||
|
@ -607,30 +607,30 @@ static void parseMapthing(FScanner &sc)
|
||||||
sc.ScriptError("Unknown property '%s'", sc.String);
|
sc.ScriptError("Unknown property '%s'", sc.String);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EDFThings[mt.recordnum] = mt;
|
EDThings[mt.recordnum] = mt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitEDF()
|
void InitED()
|
||||||
{
|
{
|
||||||
FString filename;
|
FString filename;
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
|
|
||||||
if (EDFMap.CompareNoCase(level.MapName) != 0)
|
if (EDMap.CompareNoCase(level.MapName) != 0)
|
||||||
{
|
{
|
||||||
EDFLines.Clear();
|
EDLines.Clear();
|
||||||
EDFSectors.Clear();
|
EDSectors.Clear();
|
||||||
EDFThings.Clear();
|
EDThings.Clear();
|
||||||
EDFMap = level.MapName;
|
EDMap = level.MapName;
|
||||||
|
|
||||||
const char *arg = Args->CheckValue("-edf");
|
const char *arg = Args->CheckValue("-edf");
|
||||||
|
|
||||||
if (arg != NULL) filename = arg;
|
if (arg != NULL) filename = arg;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FEdfOptions *opt = level.info->GetOptData<FEdfOptions>("EDF", false);
|
FEDOptions *opt = level.info->GetOptData<FEDOptions>("EData", false);
|
||||||
if (opt != NULL)
|
if (opt != NULL)
|
||||||
{
|
{
|
||||||
filename = opt->edfName;
|
filename = opt->EDName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,11 +662,11 @@ void InitEDF()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessEDFMapthing(FMapThing *mt, int recordnum)
|
void ProcessEDMapthing(FMapThing *mt, int recordnum)
|
||||||
{
|
{
|
||||||
InitEDF();
|
InitED();
|
||||||
|
|
||||||
EDFMapthing *emt = EDFThings.CheckKey(recordnum);
|
EDMapthing *emt = EDThings.CheckKey(recordnum);
|
||||||
if (emt == NULL)
|
if (emt == NULL)
|
||||||
{
|
{
|
||||||
Printf("EDF Mapthing record %d not found\n", recordnum);
|
Printf("EDF Mapthing record %d not found\n", recordnum);
|
||||||
|
@ -682,11 +682,11 @@ void ProcessEDFMapthing(FMapThing *mt, int recordnum)
|
||||||
mt->flags = emt->flags;
|
mt->flags = emt->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessEDFLinedef(line_t *ld, int recordnum)
|
void ProcessEDLinedef(line_t *ld, int recordnum)
|
||||||
{
|
{
|
||||||
InitEDF();
|
InitED();
|
||||||
|
|
||||||
EDFLinedef *eld = EDFLines.CheckKey(recordnum);
|
EDLinedef *eld = EDLines.CheckKey(recordnum);
|
||||||
if (eld == NULL)
|
if (eld == NULL)
|
||||||
{
|
{
|
||||||
Printf("EDF Linedef record %d not found\n", recordnum);
|
Printf("EDF Linedef record %d not found\n", recordnum);
|
||||||
|
@ -702,9 +702,9 @@ void ProcessEDFLinedef(line_t *ld, int recordnum)
|
||||||
tagManager.AddLineID(int(ld - lines), eld->tag);
|
tagManager.AddLineID(int(ld - lines), eld->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessEDFSector(sector_t *sec, int recordnum)
|
void ProcessEDSector(sector_t *sec, int recordnum)
|
||||||
{
|
{
|
||||||
EDFSector *esec = EDFSectors.CheckKey(recordnum);
|
EDSector *esec = EDSectors.CheckKey(recordnum);
|
||||||
if (esec == NULL)
|
if (esec == NULL)
|
||||||
{
|
{
|
||||||
Printf("EDF Sector record %d not found\n", recordnum);
|
Printf("EDF Sector record %d not found\n", recordnum);
|
||||||
|
@ -722,7 +722,7 @@ void ProcessEDFSector(sector_t *sec, int recordnum)
|
||||||
sec->Flags = (sec->Flags | esec->damageflags | esec->damageflagsAdd) & ~esec->damageflagsRemove;
|
sec->Flags = (sec->Flags | esec->damageflags | esec->damageflagsAdd) & ~esec->damageflagsRemove;
|
||||||
leak = (leak | esec->leaky | esec->leakyadd) & ~esec->leakyremove;
|
leak = (leak | esec->leaky | esec->leakyadd) & ~esec->leakyremove;
|
||||||
|
|
||||||
// the damage properties will be unconditionally overridden by EDF.
|
// the damage properties will be unconditionally overridden by Extradata.
|
||||||
sec->leakydamage = leak == 0 ? 0 : leak == 1 ? 5 : 256;
|
sec->leakydamage = leak == 0 ? 0 : leak == 1 ? 5 : 256;
|
||||||
sec->damageamount = esec->damageamount;
|
sec->damageamount = esec->damageamount;
|
||||||
sec->damageinterval = esec->damageinterval;
|
sec->damageinterval = esec->damageinterval;
|
||||||
|
@ -745,37 +745,37 @@ void ProcessEDFSector(sector_t *sec, int recordnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ProcessEDFSectors()
|
void ProcessEDSectors()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
InitEDF();
|
InitED();
|
||||||
if (EDFSectors.CountUsed() == 0) return; // don't waste time if there's no records.
|
if (EDSectors.CountUsed() == 0) return; // don't waste time if there's no records.
|
||||||
|
|
||||||
// collect all EDF sector records up front so we do not need to search the complete line array for each sector separately.
|
// collect all Extradata sector records up front so we do not need to search the complete line array for each sector separately.
|
||||||
int *edfsectorrecord = new int[numsectors];
|
int *sectorrecord = new int[numsectors];
|
||||||
memset(edfsectorrecord, -1, numsectors * sizeof(int));
|
memset(sectorrecord, -1, numsectors * sizeof(int));
|
||||||
for (i = 0; i < numlines; i++)
|
for (i = 0; i < numlines; i++)
|
||||||
{
|
{
|
||||||
if (lines[i].special == Static_Init && lines[i].args[1] == Init_EDFSector)
|
if (lines[i].special == Static_Init && lines[i].args[1] == Init_EDSector)
|
||||||
{
|
{
|
||||||
edfsectorrecord[lines[i].frontsector - sectors] = lines[i].args[0];
|
sectorrecord[lines[i].frontsector - sectors] = lines[i].args[0];
|
||||||
lines[i].special = 0;
|
lines[i].special = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < numsectors; i++)
|
for (i = 0; i < numsectors; i++)
|
||||||
{
|
{
|
||||||
if (edfsectorrecord[i] >= 0)
|
if (sectorrecord[i] >= 0)
|
||||||
{
|
{
|
||||||
ProcessEDFSector(§ors[i], edfsectorrecord[i]);
|
ProcessEDSector(§ors[i], sectorrecord[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] edfsectorrecord;
|
delete[] sectorrecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadMapinfoACSLump()
|
void LoadMapinfoACSLump()
|
||||||
{
|
{
|
||||||
FEdfOptions *opt = level.info->GetOptData<FEdfOptions>("EDF", false);
|
FEDOptions *opt = level.info->GetOptData<FEDOptions>("EData", false);
|
||||||
if (opt != NULL)
|
if (opt != NULL)
|
||||||
{
|
{
|
||||||
int lump = Wads.CheckNumForName(opt->acsName);
|
int lump = Wads.CheckNumForName(opt->acsName);
|
12
src/edata.h
Normal file
12
src/edata.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef EDATA_H
|
||||||
|
#define EDATA_H
|
||||||
|
|
||||||
|
struct FMapThing;
|
||||||
|
struct line_t;
|
||||||
|
|
||||||
|
void ProcessEDMapthing(FMapThing *mt, int recordnum);
|
||||||
|
void ProcessEDLinedef(line_t *line, int recordnum);
|
||||||
|
void ProcessEDSectors();
|
||||||
|
void LoadMapinfoACSLump();
|
||||||
|
|
||||||
|
#endif
|
|
@ -60,8 +60,8 @@ typedef enum {
|
||||||
Init_Damage = 2,
|
Init_Damage = 2,
|
||||||
Init_SectorLink = 3,
|
Init_SectorLink = 3,
|
||||||
NUM_STATIC_INITS,
|
NUM_STATIC_INITS,
|
||||||
Init_EDFSector = 253,
|
Init_EDSector = 253,
|
||||||
Init_EDFLine = 254,
|
Init_EDLine = 254,
|
||||||
Init_TransferSky = 255
|
Init_TransferSky = 255
|
||||||
} staticinit_t;
|
} staticinit_t;
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,8 @@
|
||||||
#include "po_man.h"
|
#include "po_man.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
#include "edf.h"
|
#include "edata.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "fragglescript/t_fs.h"
|
#include "fragglescript/t_fs.h"
|
||||||
|
@ -1770,10 +1770,10 @@ void P_LoadThings (MapData * map)
|
||||||
mti[i].info = DoomEdMap.CheckKey(mti[i].EdNum);
|
mti[i].info = DoomEdMap.CheckKey(mti[i].EdNum);
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
if (mti[i].info != NULL && mti[i].info->Special == SMT_EDFThing)
|
if (mti[i].info != NULL && mti[i].info->Special == SMT_EDFThing)
|
||||||
{
|
{
|
||||||
ProcessEDFMapthing(&mti[i], flags);
|
ProcessEDMapthing(&mti[i], flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -2173,15 +2173,15 @@ void P_LoadLineDefs (MapData * map)
|
||||||
// compatible with the new format.
|
// compatible with the new format.
|
||||||
|
|
||||||
P_TranslateLineDef (ld, mld, -1);
|
P_TranslateLineDef (ld, mld, -1);
|
||||||
// do not assign the tag for EDF lines.
|
// do not assign the tag for Extradata lines.
|
||||||
if (ld->special != Static_Init || (ld->args[1] != Init_EDFLine && ld->args[1] != Init_EDFSector))
|
if (ld->special != Static_Init || (ld->args[1] != Init_EDLine && ld->args[1] != Init_EDSector))
|
||||||
{
|
{
|
||||||
tagManager.AddLineID(i, mld->tag);
|
tagManager.AddLineID(i, mld->tag);
|
||||||
}
|
}
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
if (ld->special == Static_Init && ld->args[1] == Init_EDFLine)
|
if (ld->special == Static_Init && ld->args[1] == Init_EDLine)
|
||||||
{
|
{
|
||||||
ProcessEDFLinedef(ld, mld->tag);
|
ProcessEDLinedef(ld, mld->tag);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3702,7 +3702,7 @@ void P_SetupLevel (const char *lumpname, int position)
|
||||||
}
|
}
|
||||||
|
|
||||||
FBehavior::StaticLoadDefaultModules ();
|
FBehavior::StaticLoadDefaultModules ();
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
LoadMapinfoACSLump();
|
LoadMapinfoACSLump();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "r_sky.h"
|
#include "r_sky.h"
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
#include "edf.h"
|
#include "edata.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
|
@ -1377,8 +1377,8 @@ void P_SpawnSpecials (void)
|
||||||
P_InitSectorSpecial(sector, sector->special, false);
|
P_InitSectorSpecial(sector, sector->special, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_EDF
|
#ifndef NO_EDATA
|
||||||
ProcessEDFSectors();
|
ProcessEDSectors();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ define Unsupported (0)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Init_EDFSector = 253,
|
Init_EDSector = 253,
|
||||||
Init_EDFLine = 254
|
Init_EDLine = 254
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tag for such a line is actually a key to find, in an ExtraData lump
|
// The tag for such a line is actually a key to find, in an ExtraData lump
|
||||||
|
@ -19,7 +19,7 @@ enum
|
||||||
// to actually use. This is how parameterized linedefs are used by Eternity
|
// to actually use. This is how parameterized linedefs are used by Eternity
|
||||||
// in the Doom format.
|
// in the Doom format.
|
||||||
|
|
||||||
270 = 0, Static_Init(tag, Init_EDFLine) // "ExtraDataSpecial"
|
270 = 0, Static_Init(tag, Init_EDLine) // "ExtraDataSpecial"
|
||||||
|
|
||||||
// These two are standard MBF specials, no need to redefine them, they're in xlat/doom.txt
|
// These two are standard MBF specials, no need to redefine them, they're in xlat/doom.txt
|
||||||
// 271 = 0, Static_Init (tag, Init_TransferSky, 0)
|
// 271 = 0, Static_Init (tag, Init_TransferSky, 0)
|
||||||
|
@ -195,7 +195,7 @@ enum
|
||||||
399 = 0, Thing_SpawnNoFog(0)
|
399 = 0, Thing_SpawnNoFog(0)
|
||||||
400 = 0, Teleport_EndGame(0)
|
400 = 0, Teleport_EndGame(0)
|
||||||
|
|
||||||
401 = 0, Static_Init(tag, Init_EDFSector)
|
401 = 0, Static_Init(tag, Init_EDSector)
|
||||||
|
|
||||||
402 = 0, Thing_Projectile(0)
|
402 = 0, Thing_Projectile(0)
|
||||||
403 = 0, Thing_ProjectileGravity(0)
|
403 = 0, Thing_ProjectileGravity(0)
|
||||||
|
|
Loading…
Reference in a new issue