// Copyright © 2016-2017 Graham Sanderson, all rights reserved. // Required for sincos(3). #define _GNU_SOURCE #include "lith_upgrades_common.h" #include "lith_world.h" #include "lith_monster.h" #define UData UData_VitalScan(upgr) // Extern Functions ----------------------------------------------------------| // // Update // script void Upgr_VitalScan_Update(struct player *p, upgrade_t *upgr) { ACS_SetActivator(0, AAPTR_PLAYER_GETTARGET); bool six = ACS_StrCmp(ACS_GetActorClass(0), "RLDeVileSix", 11) == 0; bool validtarget = six || ACS_CheckFlag(0, "COUNTKILL") || ACS_PlayerNumber() != -1; if(ACS_GetActorProperty(0, APROP_Health) <= 0) UData.target = UData.oldtarget = 0; else if(validtarget) { bool legendary = world.legendoom && InvNum("LDLegendaryMonsterToken"); bool henshin = world.legendoom && InvNum("LDLegendaryMonsterTransformed"); bool phantom = InvNum("Lith_IsPhantom"); bool freak = ACS_CheckFlag(0, "INVULNERABLE") || ACS_CheckFlag(0, "NODAMAGE"); bool boss = ACS_CheckFlag(0, "BOSS"); bool shadow = ACS_CheckFlag(0, "SHADOW"); int chp = ACS_GetActorProperty(0, APROP_Health); int shp = ACS_GetActorProperty(0, APROP_SpawnHealth); int id = Lith_UniqueID(); dmon_t *m = DmonPtr(); bool healthset = false; if((freak || boss) && !phantom) { extern __str Lith_RandomName(int id); UData.tagstr = Lith_RandomName(freak ? 0 : id); if(p->getCVarI("lith_scanner_bar")) { UData.oldhealth = UData.health = ACS_Random(0, 666666); UData.maxhealth = ACS_Random(0, 666666); healthset = true; } } else { char color = p->getCVarI("lith_scanner_color") & 0x7F; if(six) UData.tagstr = "\Cg6"; else if(henshin) UData.tagstr = StrParam("\CgLegendary\C%c %tS", color, 0); else if(phantom) UData.tagstr = StrParam("\Cg%tS", 0); else UData.tagstr = StrParam("\C%c%tS", color, 0); } if(!healthset) { UData.oldhealth = UData.health; UData.health = chp; if(m) UData.maxhealth = m->maxhealth; else UData.maxhealth = shp; } if(m) { int level = shadow ? m->level - ACS_Random(-5, 5) : m->level; int nsplit = min(m->maxhealth / (fixed)shp, 7); int split = ceilk((chp / (fixed)m->maxhealth) * nsplit); int splith = m->maxhealth / (fixed)nsplit; UData.tagstr = StrParam("%S lv.%i", UData.tagstr, level); UData.rank = m->rank; UData.splitfrac = (chp - (splith * (split - 1))) / (fixed)splith; UData.split = minmax(split, 1, 7); } else { UData.rank = 0; UData.splitfrac = chp / (fixed)shp; UData.split = 1; } UData.freak = six || freak || phantom || boss; UData.cangle = ACS_VectorAngle(p->x - ACS_GetActorX(0), p->y - ACS_GetActorY(0)) * tau; if((UData.oldtarget = UData.target) != (UData.target = id)) UData.oldhealth = UData.health; } } // // Render // void Upgr_VitalScan_Render(struct player *p, upgrade_t *upgr) { if((!p->hudenabled && !(p->pclass & pcl_mods)) || !UData.target) return; int ox = p->getCVarI("lith_scanner_xoffs"); int oy = p->getCVarI("lith_scanner_yoffs"); if(p->getCVarI("lith_scanner_slide")) { float diff = p->yawf - UData.cangle; fixed ds = ACS_Sin(diff / tau) * tau; fixed dc = ACS_Cos(diff / tau) * tau; UData.oangle = lerpf(UData.oangle, atan2f(ds, dc), 0.1); ox += UData.oangle * 64; } // Rank if(UData.rank) for(int i = 1; i <= UData.rank; i++) DrawSpriteFade(StrParam(":UI:Rank%i", i), hid_vscrankS - (i - 1), 100.1 + ox + (i * 6), 216.1 + oy, 0.1, 0.1); // Hit indicator if(UData.health < UData.oldhealth) { int delta = UData.oldhealth - UData.health; HudMessageF("CBIFONT", "-%i", delta); HudMessageParams(HUDMSG_FADEOUT, hid_vschitS, CR_RED, 160.4 + ox, 235.2 + oy, 0.1, 0.4); for(int i = 1; i < 5 && delta >= 100 * i; i++) { HudMessageF("CBIFONT", "-%i", delta); HudMessageParams(HUDMSG_FADEOUT|HUDMSG_ADDBLEND, hid_vschitS - i, CR_RED, 160.4 + ox, 235.2 + oy, 0.1, 0.4); } } // Tag and health bool afnt = p->getCVarI("lith_scanner_altfont"); __str font = afnt ? "CHFONT" : "CBIFONT"; HudMessageF(font, "%S", UData.tagstr); HudMessageParams(HUDMSG_FADEOUT, hid_vsctag, CR_WHITE, 160.4 + ox, 216.2 + oy, 0.1, 0.4); ACS_SetFont(UData.freak ? "ALIENFONT" : font); if(UData.maxhealth) HudMessage("%i/%i", UData.health, UData.maxhealth); else HudMessage("%ihp", UData.health); HudMessageParams(HUDMSG_FADEOUT, hid_vschp, CR_WHITE, 160.4 + ox, 225.2 + oy, 0.1, 0.4); // Health bar if(p->getCVarI("lith_scanner_bar")) { int y = afnt ? 201 : 205; ACS_SetHudClipRect(120 + ox, y + oy, 80 * UData.splitfrac, 2); DrawSpritePlain(StrParam(":UI:HealthBar%i", UData.split), hid_vscbar, 120.1+ox, y+.1+oy, 0.1); ACS_SetHudClipRect(0, 0, 0, 0); if(UData.split > 1) DrawSpritePlain(StrParam(":UI:HealthBar%i", UData.split - 1), hid_vscbarn, 120.1+ox, y+.1+oy, 0.1); } } // EOF