- Added code submissions for non-piercing railguns and new skill options.

SVN r1706 (trunk)
This commit is contained in:
Christoph Oelckers 2009-07-04 18:17:44 +00:00
parent 3786ced96e
commit 635d71e660
25 changed files with 155 additions and 50 deletions

View file

@ -1,4 +1,7 @@
July 3, 2009
July 4, 2009 (Changes by Graf Zahl)
- Added code submissions for non-piercing railguns and new skill options.
July 3, 2009
- ZDoom now disables the input method editor, since it has no east-Asian
support, and having it open a composition window when you're only expecting
a single keypress is not so good.

View file

@ -639,6 +639,9 @@ public:
// Enter the crash state
void Crash();
// Return starting health adjusted by skill level
int SpawnHealth();
// Check for monsters that count as kill but excludes all friendlies.
bool CountsAsKill() const
{

View file

@ -768,7 +768,7 @@ CCMD(linetarget)
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->GetDefault()->health);
linetarget->SpawnHealth());
}
else Printf("No target found\n");
}

View file

@ -2129,11 +2129,13 @@ void Net_DoCommand (int type, BYTE **stream, int player)
spawned->FriendPlayer = player + 1;
spawned->flags |= MF_FRIENDLY;
spawned->LastHeard = players[player].mo;
spawned->health = spawned->SpawnHealth();
}
else if (type == DEM_SUMMONFOE || type == DEM_SUMMONFOE2)
{
spawned->FriendPlayer = 0;
spawned->flags &= ~MF_FRIENDLY;
spawned->health = spawned->SpawnHealth();
}
}
if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)

View file

@ -76,7 +76,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
}
const PClass *fx = PClass::FindClass("SorcererFX1");
if (self->health > (self->GetDefault()->health/3)*2)
if (self->health > (self->SpawnHealth()/3)*2)
{ // Spit one fireball
P_SpawnMissileZ (self, self->z + 48*FRACUNIT, self->target, fx );
}
@ -90,7 +90,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
P_SpawnMissileAngleZ (self, self->z + 48*FRACUNIT, fx, angle-ANGLE_1*3, velz);
P_SpawnMissileAngleZ (self, self->z + 48*FRACUNIT, fx, angle+ANGLE_1*3, velz);
}
if (self->health < self->GetDefault()->health/3)
if (self->health < self->SpawnHealth()/3)
{ // Maybe attack again
if (self->special1)
{ // Just attacked, so don't attack again
@ -171,7 +171,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Decide)
192, 120, 120, 120, 64, 64, 32, 16, 0
};
unsigned int chanceindex = self->health / (self->GetDefault()->health/8);
unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8);
if (chanceindex >= countof(chance))
{
chanceindex = countof(chance) - 1;
@ -205,7 +205,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack)
P_TraceBleed (damage, self->target, self);
return;
}
chance = self->health < self->GetDefault()->health/2 ? 96 : 48;
chance = self->health < self->SpawnHealth()/2 ? 96 : 48;
if (pr_s2a() < chance)
{ // Wizard spawners

View file

@ -426,7 +426,7 @@ void A_StopBalls(AActor *scary)
{
actor->StopBall = RUNTIME_CLASS(ASorcBall2); // Blue
}
else if((actor->health < (actor->GetDefault()->health >> 1)) &&
else if((actor->health < (actor->SpawnHealth() >> 1)) &&
(chance < 200))
{
actor->StopBall = RUNTIME_CLASS(ASorcBall3); // Green
@ -566,7 +566,7 @@ void ASorcBall3::CastSorcererSpell ()
ang1 = angle - ANGLE_45;
ang2 = angle + ANGLE_45;
const PClass *cls = PClass::FindClass("SorcFX3");
if (health < (GetDefault()->health/3))
if (health < (SpawnHealth()/3))
{ // Spawn 2 at a time
mo = P_SpawnMissileAngle(parent, cls, ang1, 4*FRACUNIT);
if (mo) mo->target = parent;

View file

@ -91,7 +91,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxChase)
{
AActor *spot;
if ((!self->special2) && (self->health <= (self->GetDefault()->health/2)))
if ((!self->special2) && (self->health <= (self->SpawnHealth()/2)))
{
FActorIterator iterator (KORAX_FIRST_TELEPORT_TID);
spot = iterator.Next ();
@ -117,7 +117,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxChase)
}
// Teleport away
if (self->health < (self->GetDefault()->health>>1))
if (self->health < (self->SpawnHealth()>>1))
{
if (pr_koraxchase()<10)
{
@ -261,7 +261,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxCommand)
z = self->z + KORAX_COMMAND_HEIGHT*FRACUNIT;
Spawn("KoraxBolt", x, y, z, ALLOW_REPLACE);
if (self->health <= (self->GetDefault()->health >> 1))
if (self->health <= (self->SpawnHealth() >> 1))
{
numcommands = 5;
}

View file

@ -527,7 +527,10 @@ enum ESkillProperty
SKILLP_AutoUseHealth,
SKILLP_SpawnFilter,
SKILLP_EasyBossBrain,
SKILLP_ACSReturn
SKILLP_ACSReturn,
SKILLP_MonsterHealth,
SKILLP_FriendlyHealth,
SKILLP_NoPain
};
int G_SkillProperty(ESkillProperty prop);
@ -558,6 +561,9 @@ struct FSkillInfo
FString TextColor;
SkillActorReplacement Replace;
SkillActorReplacement Replaced;
fixed_t MonsterHealth;
fixed_t FriendlyHealth;
bool NoPain;
FSkillInfo() {}
FSkillInfo(const FSkillInfo &other)

View file

@ -450,7 +450,7 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
actor->flags4 = (actor->flags4 & ~MF4_NOHATEPLAYERS) | (beast->flags4 & MF4_NOHATEPLAYERS);
if (!(beast->FlagsSave & MF_JUSTHIT))
actor->renderflags &= ~RF_INVISIBLE;
actor->health = actor->GetDefault()->health;
actor->health = actor->SpawnHealth();
actor->velx = beast->velx;
actor->vely = beast->vely;
actor->velz = beast->velz;

View file

@ -233,7 +233,7 @@ bool P_GiveBody (AActor *actor, int num)
}
else
{
max = actor->GetDefault()->health;
max = actor->SpawnHealth();
if (num < 0)
{
num = max * -num / 100;

View file

@ -72,6 +72,9 @@ void FMapInfoParser::ParseSkill ()
skill.TextColor = "";
skill.Replace.Clear();
skill.Replaced.Clear();
skill.MonsterHealth = FRACUNIT;
skill.FriendlyHealth = FRACUNIT;
skill.NoPain = false;
sc.MustGetString();
skill.Name = sc.String;
@ -226,6 +229,22 @@ void FMapInfoParser::ParseSkill ()
sc.MustGetString();
skill.TextColor.Format("[%s]", sc.String);
}
else if (sc.Compare("MonsterHealth"))
{
ParseAssign();
sc.MustGetFloat();
skill.MonsterHealth = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("FriendlyHealth"))
{
ParseAssign();
sc.MustGetFloat();
skill.FriendlyHealth = FLOAT2FIXED(sc.Float);
}
else if (sc.Compare("NoPain"))
{
skill.NoPain = true;
}
else if (!ParseCloseBrace())
{
// Unknown
@ -302,6 +321,15 @@ int G_SkillProperty(ESkillProperty prop)
case SKILLP_ACSReturn:
return AllSkills[gameskill].ACSReturn;
case SKILLP_MonsterHealth:
return AllSkills[gameskill].MonsterHealth;
case SKILLP_FriendlyHealth:
return AllSkills[gameskill].FriendlyHealth;
case SKILLP_NoPain:
return AllSkills[gameskill].NoPain;
}
}
return 0;
@ -353,6 +381,9 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other)
TextColor = other.TextColor;
Replace = other.Replace;
Replaced = other.Replaced;
MonsterHealth = other.MonsterHealth;
FriendlyHealth = other.FriendlyHealth;
NoPain = other.NoPain;
return *this;
}

View file

@ -2610,7 +2610,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
}
else
{
return actor->GetDefault()->health;
return actor->SpawnHealth();
}
case APROP_JumpZ: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))

View file

@ -1299,7 +1299,7 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index)
{
AActor *targ = other->target;
if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) &&
targ->health*2 >= targ->GetDefault()->health)
targ->health*2 >= targ->SpawnHealth())
{
continue;
}

View file

@ -199,7 +199,7 @@ AActor *LookForEnemiesInBlockEx (AActor *lookee, int index)
{
AActor *targ = other->target;
if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) &&
targ->health*2 >= targ->GetDefault()->health)
targ->health*2 >= targ->SpawnHealth())
{
continue;
}

View file

@ -319,19 +319,20 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
EXTERN_CVAR (Int, fraglimit)
static int GibHealth(AActor *actor)
{
{
return -abs(
actor->GetClass()->Meta.GetMetaInt (
AMETA_GibHealth,
gameinfo.gametype & GAME_DoomChex ?
-actor->GetDefault()->health :
-actor->GetDefault()->health/2));
-actor->SpawnHealth() :
-actor->SpawnHealth()/2));
}
void AActor::Die (AActor *source, AActor *inflictor)
{
// Handle possible unmorph on death
bool wasgibbed = (health < GibHealth(this));
AActor *realthis = NULL;
int realstyle = 0;
int realhealth = 0;
@ -1264,10 +1265,10 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
}
}
dopain:
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
(pr_damagemobj() < painchance || (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))) &&
!(target->flags & MF_SKULLFLY))
dopain:
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
!G_SkillProperty(SKILLP_NoPain) && (pr_damagemobj() < painchance ||
(inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))) && !(target->flags & MF_SKULLFLY))
{
if (mod == NAME_Electric)
{

View file

@ -993,8 +993,8 @@ FUNC(LS_DamageThing)
else
{
it->health -= arg0;
if (it->GetDefault()->health < it->health)
it->health = it->GetDefault()->health;
if (it->SpawnHealth() < it->health)
it->health = it->SpawnHealth();
}
}
else if (arg0 > 0)

View file

@ -397,7 +397,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target,
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
void P_TraceBleed (int damage, AActor *target); // random direction version
void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false, const PClass *puff = NULL); // [RH] Shoot a railgun
void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false, const PClass *puff = NULL, bool pierce = true); // [RH] Shoot a railgun
bool P_HitFloor (AActor *thing);
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false);
bool P_CheckMissileSpawn (AActor *missile);

View file

@ -3472,7 +3472,29 @@ static bool ProcessRailHit (FTraceResults &res)
return true;
}
void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent, const PClass *puffclass)
static bool ProcessNoPierceRailHit (FTraceResults &res)
{
if (res.HitType != TRACE_HitActor)
{
return false;
}
// Invulnerable things completely block the shot
if (res.Actor->flags2 & MF2_INVULNERABLE)
{
return false;
}
// Only process the first hit
SRailHit newhit;
newhit.HitActor = res.Actor;
newhit.Distance = res.Distance - 10*FRACUNIT; // put blood in front
RailHits.Push (newhit);
return false;
}
void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent, const PClass *puffclass, bool pierce)
{
fixed_t vx, vy, vz;
angle_t angle, pitch;
@ -3513,9 +3535,18 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
start.Y = FIXED2FLOAT(y1);
start.Z = FIXED2FLOAT(shootz);
Trace (x1, y1, shootz, source->Sector, vx, vy, vz,
8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
TRACE_PCross|TRACE_Impact, ProcessRailHit);
if (pierce)
{
Trace (x1, y1, shootz, source->Sector, vx, vy, vz,
8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
TRACE_PCross|TRACE_Impact, ProcessRailHit);
}
else
{
Trace (x1, y1, shootz, source->Sector, vx, vy, vz,
8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
TRACE_PCross|TRACE_Impact, ProcessNoPierceRailHit);
}
// Hurt anything the trace hit
unsigned int i;

View file

@ -859,7 +859,8 @@ void AActor::CopyFriendliness (AActor *other, bool changeTarget)
{
// LastHeard must be set as well so that A_Look can react to the new target if called
LastHeard = target = other->target;
}
}
health = SpawnHealth();
level.total_monsters += CountsAsKill();
}
@ -3369,6 +3370,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
actor->y = actor->PrevY = iy;
actor->z = actor->PrevZ = iz;
actor->picnum.SetInvalid();
actor->health = actor->SpawnHealth();
FRandom &rng = bglobal.m_Thinking ? pr_botspawnmobj : pr_spawnmobj;
@ -5256,7 +5258,7 @@ void AActor::Crash()
if (crashstate == NULL)
{
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth,
gameinfo.gametype & GAME_DoomChex ? -GetDefault()->health : -GetDefault()->health/2));
gameinfo.gametype & GAME_DoomChex ? -SpawnHealth() : -SpawnHealth()/2));
if (health < gibhealth)
{ // Extreme death
@ -5281,6 +5283,23 @@ void AActor::SetIdle()
SetState(idle);
}
int AActor::SpawnHealth()
{
if (!(flags3 & MF3_ISMONSTER) || GetDefault()->health == 0)
{
return GetDefault()->health;
}
else if (flags & MF_FRIENDLY)
{
int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_FriendlyHealth));
return (adj <= 0) ? 1 : adj;
}
else
{
int adj = FixedMul(GetDefault()->health, G_SkillProperty(SKILLP_MonsterHealth));
return (adj <= 0) ? 1 : adj;
}
}
FDropItem *AActor::GetDropItems()
{
unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1;

View file

@ -393,12 +393,12 @@ int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type)
{
P_DamageMobj (actor, NULL, whofor0, amount, type);
}
else if (actor->health < actor->GetDefault()->health)
else if (actor->health < actor->SpawnHealth())
{
actor->health -= amount;
if (actor->health > actor->GetDefault()->health)
if (actor->health > actor->SpawnHealth())
{
actor->health = actor->GetDefault()->health;
actor->health = actor->SpawnHealth();
}
if (actor->player != NULL)
{

View file

@ -1089,6 +1089,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
}
enum
{
RAF_SILENT = 1,
RAF_NOPIERCE = 2
};
//==========================================================================
//
// customizable railgun attack function
@ -1102,9 +1108,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
ACTION_PARAM_BOOL(UseAmmo, 2);
ACTION_PARAM_COLOR(Color1, 3);
ACTION_PARAM_COLOR(Color2, 4);
ACTION_PARAM_BOOL(Silent, 5);
ACTION_PARAM_INT(Flags, 5);
ACTION_PARAM_FLOAT(MaxDiff, 6);
ACTION_PARAM_CLASS(PuffType, 7);
ACTION_PARAM_CLASS(PuffType, 7);
if (!self->player) return;
@ -1116,7 +1122,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return; // out of ammo
}
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, Silent, PuffType);
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)));
}
//==========================================================================
@ -1138,7 +1144,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
ACTION_PARAM_INT(Spawnofs_XY, 1);
ACTION_PARAM_COLOR(Color1, 2);
ACTION_PARAM_COLOR(Color2, 3);
ACTION_PARAM_BOOL(Silent, 4);
ACTION_PARAM_INT(Flags, 4);
ACTION_PARAM_INT(aim, 5);
ACTION_PARAM_FLOAT(MaxDiff, 6);
ACTION_PARAM_CLASS(PuffType, 7);
@ -1201,7 +1207,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
angle_t angle = (self->angle - ANG90) >> ANGLETOFINESHIFT;
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, Silent, PuffType);
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)));
self->x = saved_x;
self->y = saved_y;

View file

@ -195,13 +195,6 @@ public:
void STACK_ARGS DrawText (FFont *font, int normalcolor, int x, int y, const char *string, ...);
void STACK_ARGS DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, ...);
protected:
BYTE *Buffer;
int Width;
int Height;
int Pitch;
int LockCount;
struct DrawParms
{
fixed_t x, y;
@ -234,6 +227,13 @@ protected:
FRenderStyle style;
};
protected:
BYTE *Buffer;
int Width;
int Height;
int Pitch;
int LockCount;
bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const;
virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const;

View file

@ -175,7 +175,7 @@ ACTOR Actor native //: Thinker
action native A_Jump(int chance, state label, ...);
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, bool aimfacing = false);
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", bool silent = false, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_JumpIfHealthLower(int health, state label);
action native A_JumpIfCloser(float distance, state label);
action native A_JumpIfInventory(class<Inventory> itemtype, int itemamount, state label);

View file

@ -51,6 +51,9 @@ const int MRF_UNDOBYDEATH = 512;
const int MRF_UNDOBYDEATHFORCED = 1024;
const int MRF_UNDOBYDEATHSAVES = 2048;
const int RGF_SILENT = 1;
const int RGF_NOPIERCING = 2;
// constants for A_PlaySound
enum
{

View file

@ -9,7 +9,7 @@ ACTOR Inventory native
action native A_CustomPunch(int damage, bool norandom = false, bool useammo = true, class<Actor> pufftype = "BulletPuff", float range = 0);
action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", bool useammo = true, float range = 0);
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0);
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", bool silent = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
action native A_Light(int extralight);
action native A_Light0();
action native A_Light1();