Save/load system stability improvements.
This commit is contained in:
parent
039d9937e9
commit
8ec3d00e93
30 changed files with 265 additions and 83 deletions
|
@ -50,9 +50,9 @@ public:
|
|||
virtual void Spawned(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual int GlobalPresent(string);
|
||||
virtual void AddNewGlobal(string, globalstate_t);
|
||||
virtual void SetGlobal(string, globalstate_t);
|
||||
nonvirtual int GlobalPresent(string);
|
||||
nonvirtual void AddNewGlobal(string, globalstate_t);
|
||||
nonvirtual void SetGlobal(string, globalstate_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
virtual void SpawnKey(string,string);
|
||||
virtual void Respawn(void);
|
||||
|
||||
virtual void Play(entity, triggermode_t);
|
||||
nonvirtual void Play(entity, triggermode_t);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void Respawn(void);
|
||||
virtual void ShootGib(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
nonvirtual void ShootGib(void);
|
||||
|
||||
private:
|
||||
int m_iGibs;
|
||||
|
|
|
@ -61,8 +61,8 @@ public:
|
|||
virtual void Spawned(void);
|
||||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void CreateSpark(void);
|
||||
virtual void TimedSpark(void);
|
||||
nonvirtual void CreateSpark(void);
|
||||
nonvirtual void TimedSpark(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
virtual void Touch(entity);
|
||||
virtual void Blocked(entity);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void DeathTrigger(void);
|
||||
nonvirtual void DeathTrigger(void);
|
||||
virtual void PlayerUse(void);
|
||||
|
||||
virtual void MoverStartsMoving(void);
|
||||
|
|
|
@ -49,10 +49,10 @@ public:
|
|||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void Death(void);
|
||||
|
||||
virtual void NextPath(void);
|
||||
virtual void Move(void);
|
||||
virtual void Start(void);
|
||||
virtual void Stop(void);
|
||||
nonvirtual void NextPath(void);
|
||||
nonvirtual void Move(void);
|
||||
nonvirtual void Start(void);
|
||||
nonvirtual void Stop(void);
|
||||
|
||||
virtual void Input(entity, string, string);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
virtual void Respawn(void);
|
||||
|
||||
virtual void OnPlayerUse(void);
|
||||
virtual void ResetHealth(void);
|
||||
nonvirtual void ResetHealth(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -61,10 +61,10 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual void Fire(vector);
|
||||
virtual void FireRandom(void);
|
||||
virtual void FireTarget(entity);
|
||||
virtual void FireControlled(void);
|
||||
nonvirtual void Fire(vector);
|
||||
nonvirtual void FireRandom(void);
|
||||
nonvirtual void FireTarget(entity);
|
||||
nonvirtual void FireControlled(void);
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -66,10 +66,10 @@ public:
|
|||
virtual void Touch(entity);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual void Move(vector, vector, void(void));
|
||||
virtual void ArrivedUp(void);
|
||||
virtual void ArrivedDown(void);
|
||||
virtual void MoveToggle(void);
|
||||
nonvirtual void Move(vector, vector, void(void));
|
||||
nonvirtual void ArrivedUp(void);
|
||||
nonvirtual void ArrivedDown(void);
|
||||
nonvirtual void MoveToggle(void);
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -51,7 +51,7 @@ func_recharge:NSRenderableEntity
|
|||
virtual void customphysics(void);
|
||||
|
||||
virtual void OnPlayerUse(void);
|
||||
virtual void ResetHealth(void);
|
||||
nonvirtual void ResetHealth(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -80,13 +80,13 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Touch(entity);
|
||||
virtual void Death(void);
|
||||
|
||||
virtual void ArrivedClosed(void);
|
||||
virtual void ArrivedOpened(void);
|
||||
virtual void TriggerTargets(void);
|
||||
virtual void Rotate(vector, void());
|
||||
virtual void TurnToggle(void);
|
||||
virtual void OnPlayerUse(void);
|
||||
|
||||
nonvirtual void ArrivedClosed(void);
|
||||
nonvirtual void ArrivedOpened(void);
|
||||
nonvirtual void TriggerTargets(void);
|
||||
nonvirtual void Rotate(vector, void());
|
||||
nonvirtual void TurnToggle(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -97,9 +97,9 @@ public:
|
|||
virtual void customphysics(void);
|
||||
virtual void PlayerInput(void);
|
||||
virtual void Respawn(void);
|
||||
virtual void SpriteSmoke(vector);
|
||||
virtual void SpriteFlash(vector);
|
||||
virtual void SpawnKey(string,string);
|
||||
nonvirtual void SpriteSmoke(vector);
|
||||
nonvirtual void SpriteFlash(vector);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -71,12 +71,12 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void SoundMove(void);
|
||||
virtual void SoundStop(void);
|
||||
virtual void AfterSpawn(void);
|
||||
virtual void PathNext(void);
|
||||
virtual void PathMove(void);
|
||||
virtual void PathDone(void);
|
||||
nonvirtual void SoundMove(void);
|
||||
nonvirtual void SoundStop(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
nonvirtual void PathNext(void);
|
||||
nonvirtual void PathMove(void);
|
||||
nonvirtual void PathDone(void);
|
||||
virtual void Blocked(entity);
|
||||
|
||||
};
|
||||
|
|
|
@ -74,12 +74,12 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void SoundMove(void);
|
||||
virtual void SoundStop(void);
|
||||
virtual void AfterSpawn(void);
|
||||
virtual void PathNext(void);
|
||||
virtual void PathMove(void);
|
||||
virtual void PathDone(void);
|
||||
nonvirtual void SoundMove(void);
|
||||
nonvirtual void SoundStop(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
nonvirtual void PathNext(void);
|
||||
nonvirtual void PathMove(void);
|
||||
nonvirtual void PathDone(void);
|
||||
virtual void Blocked(entity);
|
||||
};
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual int GetCount(void);
|
||||
virtual void SetCount(int);
|
||||
nonvirtual int GetCount(void);
|
||||
nonvirtual void SetCount(int);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual void SpawnUnit(string,vector);
|
||||
nonvirtual void SpawnUnit(string,vector);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
void info_null(void);
|
||||
|
||||
#ifdef DEBUG_INFONULL
|
||||
virtual void WarnDeveloper(void);
|
||||
nonvirtual void WarnDeveloper(void);
|
||||
virtual void Respawn(void);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ item_food:NSRenderableEntity
|
|||
virtual void Respawn(void);
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void Setup(void);
|
||||
nonvirtual void Setup(void);
|
||||
virtual void Touch(entity);
|
||||
};
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void RestoreComplete(void);
|
||||
|
||||
virtual void Processing(void);
|
||||
nonvirtual void Processing(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -66,9 +66,9 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void Spawner(void);
|
||||
virtual void TurnOn(void);
|
||||
virtual void TurnOff(void);
|
||||
nonvirtual void Spawner(void);
|
||||
nonvirtual void TurnOn(void);
|
||||
nonvirtual void TurnOff(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
virtual void SpawnKey(string,string);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void ReloadSave(void);
|
||||
nonvirtual void ReloadSave(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -38,10 +38,10 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual void Interact(void);
|
||||
virtual void Turn(vector,void(void));
|
||||
virtual void Opened(void);
|
||||
virtual void Closed(void);
|
||||
nonvirtual void Interact(void);
|
||||
nonvirtual void Turn(vector,void(void));
|
||||
nonvirtual void Opened(void);
|
||||
nonvirtual void Closed(void);
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -56,9 +56,9 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void PlaySample(void);
|
||||
virtual void Enable(void);
|
||||
virtual void Disable(void);
|
||||
nonvirtual void PlaySample(void);
|
||||
nonvirtual void Enable(void);
|
||||
nonvirtual void Disable(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -106,10 +106,10 @@ public:
|
|||
virtual void Trigger(entity, triggermode_t);
|
||||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
||||
virtual void RunOnEntity(entity);
|
||||
virtual void InitIdle(void);
|
||||
virtual void Touch(entity);
|
||||
|
||||
nonvirtual void RunOnEntity(entity);
|
||||
nonvirtual void InitIdle(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void Trigger(entity, triggermode_t);
|
||||
|
||||
virtual void Announce(void);
|
||||
nonvirtual void Announce(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void RestoreComplete(void);
|
||||
|
||||
virtual void Processing(void);
|
||||
nonvirtual void Processing(void);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ void TraceAttack_SetPenetrationPower(int power);
|
|||
|
||||
/** This class handles traceline/hitscan attacks. */
|
||||
class
|
||||
NSTraceAttack
|
||||
NSTraceAttack:NSIO
|
||||
{
|
||||
private:
|
||||
/* multi-part damage */
|
||||
|
@ -55,6 +55,11 @@ private:
|
|||
public:
|
||||
void NSTraceAttack(void);
|
||||
|
||||
/* overrides */
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void RestoreComplete(void);
|
||||
|
||||
/** Call once your parameters are set up to cast the trace/hitscan */
|
||||
virtual void Fire(void);
|
||||
|
||||
|
|
|
@ -14,6 +14,107 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
void
|
||||
NSTraceAttack::NSTraceAttack(void)
|
||||
{
|
||||
m_eMultiTarget = __NULL__;
|
||||
m_iMultiValue = 0;
|
||||
m_iMultiBody = 0;
|
||||
m_flRange = 8196;
|
||||
//m_iDecalGroup = -1;
|
||||
m_strDecalGroup = __NULL__;
|
||||
|
||||
#ifdef BULLETPENETRATION
|
||||
m_flMaxThickness = 5.0f;
|
||||
m_flRangeModifier = 1.0f;
|
||||
m_iTotalPenetrations = 0;
|
||||
#endif
|
||||
|
||||
identity = 1;
|
||||
};
|
||||
|
||||
void
|
||||
NSTraceAttack::Save(float handle)
|
||||
{
|
||||
SaveEntity(handle, "m_eMultiTarget", m_eMultiTarget);
|
||||
SaveInt(handle, "m_iMultiValue", m_iMultiValue);
|
||||
SaveInt(handle, "m_iMultiBody", m_iMultiBody);
|
||||
SaveInt(handle, "m_iShots", m_iShots);
|
||||
SaveFloat(handle, "m_flDamage", m_flDamage);
|
||||
SaveVector(handle, "m_vecSpread", m_vecSpread);
|
||||
SaveInt(handle, "m_iWeapon", m_iWeapon);
|
||||
SaveEntity(handle, "m_eOwner", m_eOwner);
|
||||
SaveFloat(handle, "m_flRange", m_flRange);
|
||||
SaveVector(handle, "m_vecOrigin", m_vecOrigin);
|
||||
SaveString(handle, "m_strDecalGroup", m_strDecalGroup);
|
||||
|
||||
#ifdef BULLETPENETRATION
|
||||
SaveFloat(handle, "m_flMaxThickness", m_flMaxThickness);
|
||||
SaveFloat(handle, "m_flRangeModifier", m_flRangeModifier);
|
||||
SaveInt(handle, "m_iTotalPenetrations", m_iTotalPenetrations);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
NSTraceAttack::RestoreComplete(void)
|
||||
{
|
||||
g_traceAttack = this;
|
||||
}
|
||||
|
||||
void
|
||||
NSTraceAttack::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_eMultiTarget":
|
||||
m_eMultiTarget = ReadEntity(strValue);
|
||||
break;
|
||||
case "m_iMultiValue":
|
||||
m_iMultiValue = ReadInt(strValue);
|
||||
break;
|
||||
case "m_iMultiBody":
|
||||
m_iMultiBody = ReadInt(strValue);
|
||||
break;
|
||||
|
||||
case "m_iShots":
|
||||
m_iShots = ReadInt(strValue);
|
||||
break;
|
||||
case "m_flDamage":
|
||||
m_flDamage = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_vecSpread":
|
||||
m_vecSpread = ReadVector(strValue);
|
||||
break;
|
||||
case "m_iWeapon":
|
||||
m_iWeapon = ReadInt(strValue);
|
||||
break;
|
||||
case "m_eOwner":
|
||||
m_eOwner = ReadEntity(strValue);
|
||||
break;
|
||||
case "m_flRange":
|
||||
m_flRange = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_vecOrigin":
|
||||
m_vecOrigin = ReadVector(strValue);
|
||||
break;
|
||||
case "m_strDecalGroup":
|
||||
m_strDecalGroup = ReadString(strValue);
|
||||
break;
|
||||
|
||||
/* bullet penetration */
|
||||
#ifdef BULLETPENETRATION
|
||||
case "m_flMaxThickness":
|
||||
m_flMaxThickness = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_flRangeModifier":
|
||||
m_flRangeModifier = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_iTotalPenetrations":
|
||||
m_iTotalPenetrations = ReadInt(strValue);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSTraceAttack::_ApplyDamage(void)
|
||||
{
|
||||
|
@ -277,23 +378,6 @@ NSTraceAttack::SetPenetrationPower(int iPower)
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
NSTraceAttack::NSTraceAttack(void)
|
||||
{
|
||||
m_eMultiTarget = __NULL__;
|
||||
m_iMultiValue = 0;
|
||||
m_iMultiBody = 0;
|
||||
m_flRange = 8196;
|
||||
//m_iDecalGroup = -1;
|
||||
m_strDecalGroup = __NULL__;
|
||||
|
||||
#ifdef BULLETPENETRATION
|
||||
m_flMaxThickness = 5.0f;
|
||||
m_flRangeModifier = 1.0f;
|
||||
m_iTotalPenetrations = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* fire a given amount of shots */
|
||||
void
|
||||
TraceAttack_FireBullets(int iShots, vector vecPos, int iDamage, vector vecSpread, int iWeapon)
|
||||
|
|
|
@ -418,7 +418,9 @@ initents(void)
|
|||
Sound_Precache("damage_bullet.hit");
|
||||
Sound_Precache("player.spraylogo");
|
||||
|
||||
Game_InitRules();
|
||||
if (!g_grMode)
|
||||
Game_InitRules();
|
||||
|
||||
Game_Worldspawn();
|
||||
Decals_Init();
|
||||
Sentences_Init();
|
||||
|
@ -634,6 +636,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots)
|
|||
print("--------- Loading Existing Save ----------\n");
|
||||
g_isloading = true;
|
||||
|
||||
#if 0
|
||||
/* mark anything else for deletion */
|
||||
while ((e=nextent(e))) {
|
||||
if (edict_num(1) != e) {
|
||||
|
@ -643,6 +646,7 @@ SV_PerformLoad(float fh, float entcount, float playerslots)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REEDICT
|
||||
while ((e=nextent(e))) {
|
||||
|
|
|
@ -366,6 +366,30 @@ NSIO::Save(float handle)
|
|||
SaveString(handle, "noise2", noise2);
|
||||
SaveString(handle, "noise3", noise3);
|
||||
|
||||
/* FTEQW relevant fields */
|
||||
SaveFloat(handle, "dimension_solid", dimension_solid);
|
||||
SaveFloat(handle, "dimension_hit", dimension_hit);
|
||||
SaveFloat(handle, "frame1time", frame1time);
|
||||
SaveFloat(handle, "basebone", basebone);
|
||||
SaveFloat(handle, "baseframe", baseframe);
|
||||
SaveFloat(handle, "drawflags", drawflags);
|
||||
SaveString(handle, "customphysics", getentityfieldstring(findentityfield("customphysics"), this));
|
||||
SaveFloat(handle, "dimension_see", dimension_see);
|
||||
SaveFloat(handle, "dimension_seen", dimension_seen);
|
||||
SaveFloat(handle, "dimension_seen", dimension_seen);
|
||||
SaveString(handle, "SendEntity", getentityfieldstring(findentityfield("SendEntity"), this));
|
||||
SaveFloat(handle, "Version", Version);
|
||||
SaveFloat(handle, "viewzoom", viewzoom);
|
||||
SaveFloat(handle, "uniquespawnid", uniquespawnid);
|
||||
|
||||
/* Nuclide global fields */
|
||||
SaveFloat(handle, "jumptime", jumptime);
|
||||
SaveFloat(handle, "identity", identity);
|
||||
SaveFloat(handle, "iBleeds", iBleeds);
|
||||
SaveFloat(handle, "subblend2frac", subblend2frac);
|
||||
SaveFloat(handle, "subblendfrac", subblendfrac);
|
||||
SaveFloat(handle, "baseframe1time", baseframe1time);
|
||||
|
||||
SaveString(handle, "m_strOnTrigger", m_strOnTrigger);
|
||||
SaveString(handle, "m_strOnUser1", m_strOnUser1);
|
||||
SaveString(handle, "m_strOnUser2", m_strOnUser2);
|
||||
|
@ -612,6 +636,71 @@ NSIO::Restore(string strKey, string strValue)
|
|||
case "noise3":
|
||||
noise3 = ReadString(strValue);
|
||||
break;
|
||||
|
||||
/* FTEQW relevant fields */
|
||||
case "dimension_solid":
|
||||
dimension_solid = ReadFloat(strValue);
|
||||
break;
|
||||
case "dimension_hit":
|
||||
dimension_hit = ReadFloat(strValue);
|
||||
break;
|
||||
case "frame1time":
|
||||
frame1time = ReadFloat(strValue);
|
||||
break;
|
||||
case "basebone":
|
||||
basebone = ReadFloat(strValue);
|
||||
break;
|
||||
case "baseframe":
|
||||
baseframe = ReadFloat(strValue);
|
||||
break;
|
||||
case "drawflags":
|
||||
drawflags = ReadFloat(strValue);
|
||||
break;
|
||||
case "customphysics":
|
||||
customphysics = externvalue(-1, strValue);
|
||||
break;
|
||||
case "dimension_see":
|
||||
dimension_see = ReadFloat(strValue);
|
||||
break;
|
||||
case "dimension_seen":
|
||||
dimension_seen = ReadFloat(strValue);
|
||||
break;
|
||||
case "dimension_seen":
|
||||
dimension_seen = ReadFloat(strValue);
|
||||
break;
|
||||
case "SendEntity":
|
||||
SendEntity = externvalue(-1, strValue);
|
||||
break;
|
||||
case "Version":
|
||||
Version = ReadFloat(strValue);
|
||||
break;
|
||||
case "viewzoom":
|
||||
viewzoom = ReadFloat(strValue);
|
||||
break;
|
||||
case "uniquespawnid":
|
||||
uniquespawnid = ReadFloat(strValue);
|
||||
break;
|
||||
|
||||
/* Nuclide global fields */
|
||||
case "jumptime":
|
||||
jumptime = ReadFloat(strValue);
|
||||
break;
|
||||
case "identity":
|
||||
identity = ReadFloat(strValue);
|
||||
break;
|
||||
case "iBleeds":
|
||||
iBleeds = ReadFloat(strValue);
|
||||
break;
|
||||
case "subblend2frac":
|
||||
subblend2frac = ReadFloat(strValue);
|
||||
break;
|
||||
case "subblendfrac":
|
||||
subblendfrac = ReadFloat(strValue);
|
||||
break;
|
||||
case "baseframe1time":
|
||||
baseframe1time = ReadFloat(strValue);
|
||||
break;
|
||||
|
||||
/* END: all the stock Quake fields the engine is aware of */
|
||||
case "m_strOnTrigger":
|
||||
m_strOnTrigger = ReadString(strValue);
|
||||
|
|
Loading…
Reference in a new issue