Raw model (for completeness)
{
"meta": {
"id": "06bb42c4-964a-4f6f-a104-78b0bb1b4c9c",
"sha1": "69932d573fdbc31cfb3e1dc9ad1e35636c69c74f",
"sha256": "aa5dfceab343d3807472ffdf737c5f3de2ab3198a83e2ade28084b319f3e718d",
"filenames": [
"greendemon_zandro_test.pk3"
],
"additional": {
"engines": [],
"iwad": [],
"filename": null,
"added": "2022/02/23 23:30:56",
"locked": false,
"canDownload": true,
"adult": false,
"hidden": false,
"name": null,
"description": null,
"maps": null,
"graphicOverrides": null,
"screenshots": null,
"palettes": null,
"categories": null
},
"flags": {
"locked": false,
"canDownload": true,
"adult": false,
"hidden": false
},
"added": "2022/02/23 23:30:56",
"file": {
"type": "PK3",
"size": 663002,
"url": "https://wadarchive2.nyc3.digitaloceanspaces.com/69932d573fdbc31cfb3e1dc9ad1e35636c69c74f/69932d573fdbc31cfb3e1dc9ad1e35636c69c74f.pk3.gz",
"corrupt": false
},
"content": {
"counts": {
"endoom": 0,
"graphics": 0,
"lumps": 16,
"maps": 0,
"palettes": 0
}
},
"text_files": [
{
"source": "pk3",
"name": "chase_zscript.txt",
"contents": "/*\nideas from Thorsten Huber:\n- Extra hard mode (as a variable): make the player actually weaker than regular doomguy (maybe due to the point of dealing minimalistic/no damage at all) when far away from the green demon. Maybe with the trade-off that it gives you 8x if really close? That could ramp up the love/hate-relationship even more.\nIdeas from people in the chat that I liked and you maybe didn't to time to read:\n- Shoot at the green demon and draw it back a bit\n- Make the demon slow down in walls/when gibbing enemies\n- Killing enemies speeds you up/makes you shoot faster\n*/\n\nclass ChaseHandler : EventHandler\n{\n // when player leaves this range from start spot, chaser will spawn\n const EXIT_SPAWN_RANGE = 100;\n\n Chaser ch;\n Vector3 playerStartPos;\n int chaserSpawnTime;\n bool chaserSpawnQueued;\n TextureID radarIcon;\n ui transient Font bigFont;\n\n override void OnRegister()\n {\n radarIcon = TexMan.CheckForTexture(\"skulldar\", 0);\n }\n\n const UI_WIDTH = 320;\n const UI_HEIGHT = 240;\n\n override void RenderOverlay(RenderEvent e)\n {\n Vector2 textPos = (UI_WIDTH / 2, 60);\n Vector2 iconPos = (UI_WIDTH / 2, 10);\n if ( !(bigFont) )\n bigFont = Font.GetFont(\"BIGFONT\");\n PlayerPawn p = players[consoleplayer].mo;\n if ( !(p) || !(ch) )\n return;\n // indicate damage bonus\n double distanceToPlayer = ch.Distance3D(p);\n if ( CVar.FindCVar(\"chaser_prox_bonuses\").GetBool() == true )\n {\n String bonus = \"\";\n Color c = Font.CR_YELLOW;\n if ( distanceToPlayer <= ch.DAMAGE_BONUS_RANGE_INNER )\n {\n bonus = String.Format(\"%i X\", ch.DAMAGE_BONUS_MAX);\n c = Font.CR_RED;\n }\n else if ( distanceToPlayer <= ch.DAMAGE_BONUS_RANGE_OUTER )\n bonus = String.Format(\"%i X\", ch.DAMAGE_BONUS_MIN);\n if ( bonus != \"\" )\n {\n\t\ttextPos.x -= bigFont.StringWidth(bonus) / 2;\n\t\tScreen.DrawText(bigFont, c, textPos.x, textPos.y, bonus,\n\t\t\t\tDTA_VirtualWidth, UI_WIDTH,\n\t\t\t\tDTA_VirtualHeight, UI_HEIGHT);\n }\n }\n // radar for player\n int a = p.AngleTo(ch) - p.angle;\n a = abs(a) % 360;\n a -= 180;\n double iconAlpha = abs(a) / 180.0;\n // ramp up visibility only when angle is close\n iconAlpha /= 2.5;\n iconAlpha -= 0.125;\n if ( iconAlpha <= 0 )\n return;\n double iconScale = 0.7 + iconAlpha;\n\tint iconW, iconH;\n\t[iconW, iconH] = TexMan.GetSize(radarIcon);\n iconScale *= 0.5;\n\ticonW *= iconScale;\n\ticonPos.x -= iconW / 2;\n\ticonH *= iconScale;\n iconAlpha *= 1.5;\n Vector2 box = (-1, -1);\n\tScreen.DrawTexture(radarIcon, false, iconPos.x, iconPos.y,\n\t\t\t DTA_VirtualWidth, UI_WIDTH,\n\t\t\t DTA_VirtualHeight, UI_HEIGHT,\n\t\t\t DTA_DestWidth, iconW, DTA_DestHeight, iconH,\n\t\t\t DTA_Alpha, iconAlpha);\n }\n\n override void PlayerEntered(PlayerEvent e)\n {\n playerStartPos = players[e.PlayerNumber].mo.pos;\n chaserSpawnQueued = false;\n chaserSpawnTime = -1;\n }\n\n override void WorldTick()\n {\n PlayerPawn p = players[consoleplayer].mo;\n if ( level.maptime == chaserSpawnTime )\n {\n ch = Chaser(p.Spawn(\"Chaser\", playerStartPos));\n ch.handler = self;\n ch.A_PlaySound(\"ChaserSpawn\");\n }\n if ( !chaserSpawnQueued )\n {\n double distFromStart = (p.pos - playerStartPos).Length();\n if ( distFromStart > EXIT_SPAWN_RANGE )\n {\n chaserSpawnTime = level.maptime;\n double spawnDelay = CVar.FindCVar(\"chaser_spawn_delay\").GetFloat();\n chaserSpawnTime += max(1, spawnDelay * 35);\n chaserSpawnQueued = true;\n }\n }\n }\n}\n\nclass Chaser : Actor\n{\n const DAMAGE_BONUS_RANGE_OUTER = 800;\n const DAMAGE_BONUS_RANGE_INNER = 250;\n // when player is within outer range, MIN bonuses apply\n const DAMAGE_BONUS_MIN = 2;\n const DAMAGE_RESIST_MIN = 0.5;\n // when player is within inner range, MAX bonuses apply\n const DAMAGE_BONUS_MAX = 6;\n const DAMAGE_RESIST_MAX = 0.1;\n const SOUND_COOLDOWN = 1;\n\n ChaseHandler handler;\n Actor viz;\n int lastSoundTime;\n int collideDamage;\n\n Default\n {\n Radius 8; // low radius = high drama\n Height 40; // float this distance above ground\n Speed 5;\n +NOGRAVITY;\n +MOVEWITHSECTOR;\n -SOLID;\n }\n\n override void PostBeginPlay()\n {\n Super.PostBeginPlay();\n A_PlaySound(\"ChaserAmb\", CHAN_AUTO, 1.0, true, ATTN_NORM);\n // second amb with shorter radius\n A_PlaySound(\"ChaserAmb2\", CHAN_AUTO, 0.25, true, ATTN_STATIC);\n viz = Spawn(\"VisibleChaser\", pos);\n lastSoundTime = -SOUND_COOLDOWN * 35;\n }\n\n override string GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack)\n {\n return \"%o was annihilated by the Green Demon.\";\n }\n\n void Kill(Actor victim)\n {\n victim.DamageMobj(self, self, collideDamage, 'Massacre');\n players[consoleplayer].mo.A_PlaySound(\"ChaserKill\", CHAN_AUTO);\n }\n\n override void Tick()\n {\n Super.Tick();\n collideDamage = CVar.FindCVar(\"chaser_invuln_works\").GetBool() == true ? 8000 : 1000000;\n Speed = CVar.FindCVar(\"chaser_speed\").GetFloat();\n PlayerPawn p = players[consoleplayer].mo;\n if ( !(p) )\n return;\n // move towards (living) player\n if ( p.Health > 0 )\n {\n double a = AngleTo(p);\n // wobble path to player if they have blur sphere\n bool hasInviso = p.FindInventory(\"PowerInvisibility\");\n if ( hasInviso )\n a += sin(level.maptime) * 40;\n // calc XY separately, as we don't like\n // Vec3Angle's Z result\n Vector2 newDir = Vec2Angle(Speed, a);\n Vector3 d = (pos - p.pos).Unit();\n Vector3 newPos = (newDir.x, newDir.y, d.z);\n SetOrigin(newPos, true);\n newPos.z += Height;\n viz.SetOrigin(newPos, true);\n viz.angle = a;\n }\n // gib player if they're touching\n double distanceToPlayer = Distance2D(p);\n if ( distanceToPlayer <= Radius + p.Radius && p.Health > 0 &&\n abs(pos.z - p.pos.z) <= Height + p.Height )\n {\n Kill(p);\n }\n // gib monsters too\n if ( CVar.FindCVar(\"chaser_kill_monsters\").GetBool() == true )\n {\n BlockThingsIterator bti = BlockThingsIterator.Create(self, Radius);\n while ( bti.Next() )\n {\n if ( ( (bti.thing.bIsMonster && bti.thing.Health > 0) ||\n (bti.thing is \"ExplosiveBarrel\") ) &&\n Distance2D(bti.thing) <= Radius + bti.thing.Radius &&\n abs(bti.thing.pos.z - pos.z) <= bti.thing.Height + Height )\n {\n Kill(bti.thing);\n }\n }\n }\n // player's damage multiplier and resistance change within proximity\n if ( CVar.FindCVar(\"chaser_prox_bonuses\").GetBool() == true )\n {\n if ( distanceToPlayer <= DAMAGE_BONUS_RANGE_INNER )\n {\n p.DamageMultiply = DAMAGE_BONUS_MAX;\n p.DamageFactor = DAMAGE_RESIST_MAX;\n }\n else if ( distanceToPlayer <= DAMAGE_BONUS_RANGE_OUTER )\n {\n p.DamageMultiply = DAMAGE_BONUS_MIN;\n p.DamageFactor = DAMAGE_RESIST_MIN;\n }\n else\n {\n p.DamageMultiply = 1;\n p.DamageFactor = 1;\n }\n // if player is attacking, play sound for that bonus level\n if ( p.InStateSequence(p.CurState, p.ResolveState(\"Missile\")) &&\n level.maptime > lastSoundTime + SOUND_COOLDOWN * 35 )\n {\n String snd;\n if ( p.DamageMultiply == DAMAGE_BONUS_MIN )\n snd = \"ChaserProx1\";\n else if ( p.DamageMultiply == DAMAGE_BONUS_MAX )\n snd = \"ChaserProx2\";\n if ( snd != \"\" )\n {\n p.A_PlaySound(snd, CHAN_AUTO);\n lastSoundTime = level.maptime;\n }\n }\n }\n else\n {\n p.DamageMultiply = 1;\n p.DamageFactor = 1;\n }\n // glitter trail\n if ( level.maptime % 1 == 0 ) // (1 = every frame)\n {\n Vector3 gpos = viz.pos;\n gpos.x += random(-16, 16);\n gpos.y += random(-16, 16);\n gpos.z += random(-16, 16);\n Spawn(\"ChaserGlitter\", gpos);\n }\n }\n}\n\n// the actual visible orb, draw at a Z offset from the actual object's pos\nclass VisibleChaser : Actor\n{\n int lastSkin;\n\n Default\n {\n +NOBLOCKMAP;\n +NOGRAVITY;\n +FLOATBOB;\n }\n\n override void Tick()\n {\n Super.Tick();\n int skin = CVar.FindCVar(\"chaser_skin\").GetInt();\n if ( lastSkin != skin )\n {\n switch( skin )\n {\n case 0:\n {\n SetStateLabel(\"Doom\");\n break;\n }\n case 1:\n {\n SetStateLabel(\"Classic\");\n // TODO: set scale\n break;\n }\n case 2:\n {\n SetStateLabel(\"Otto\");\n break;\n }\n case 3:\n {\n SetStateLabel(\"Bob\");\n break;\n }\n case 4:\n {\n SetStateLabel(\"Richard\");\n break;\n }\n default:\n {\n SetStateLabel(\"Doom\");\n Console.Printf(\"invalid value for chaser_skin\");\n }\n }\n }\n Scale = skin == 0 ? (1.25, 1.25) : (0.5, 0.5);\n lastSkin = skin;\n }\n\n States\n {\n Spawn:\n Goto Doom;\n Doom:\n PINV ABCD 8 Bright;\n Loop;\n Classic:\n m1up A 8 Bright;\n Loop;\n Otto:\n otto A 8 Bright;\n Loop;\n Bob:\n tbob A 8 Bright;\n Loop;\n Richard:\n rdjf A 8 Bright;\n Loop;\n }\n}\n\nclass ChaserGlitter : Actor\n{\n const Z_CHANGE_PER_TICK = 1;\n const ALPHA_DECAY_RATE = 0.015;\n\n Default\n {\n +NOBLOCKMAP;\n +NOGRAVITY;\n -SOLID;\n RenderStyle \"Shaded\";\n StencilColor \"Black\";\n Scale 1.0;\n }\n\n override void Tick()\n {\n Super.Tick();\n Vector3 newpos = pos;\n newpos.z += Z_CHANGE_PER_TICK;\n SetOrigin(newpos, true);\n alpha -= ALPHA_DECAY_RATE;\n if ( alpha <= 0 )\n Destroy();\n }\n\n States\n {\n Spawn:\n IFOG ABCDE 8 Bright;\n Stop;\n }\n}"
},
{
"source": "pk3",
"name": "cvarinfo.txt",
"contents": "server float chaser_speed = 5;\nserver float chaser_spawn_delay = 1;\nserver bool chaser_prox_bonuses = true;\nserver bool chaser_invuln_works = true;\nserver int chaser_skin = 0;\nserver bool chaser_kill_monsters = true;"
},
{
"source": "pk3",
"name": "mapinfo.txt",
"contents": "GameInfo\n{\n AddEventHandlers = \"ChaseHandler\"\n}"
},
{
"source": "pk3",
"name": "sndinfo.txt",
"contents": "ChaserSpawn sounds/chaser_spawn.ogg\nChaserKill sounds/chaser_kill.ogg\nChaserAmb sounds/chaser_amb.ogg\nChaserAmb2 sounds/chaser_amb2.ogg\nChaserProx1 sounds/chaser_bonus1.ogg\nChaserProx2 sounds/chaser_bonus2.ogg"
},
{
"source": "pk3",
"name": "zscript.txt",
"contents": "version \"3.3.0\"\n\n#include \"chase_zscript.txt\""
}
]
},
"maps": []
}