From fb83735877a5aced5699155d6394049b2ff1e96a Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 1 Sep 2013 02:22:26 +1000 Subject: [PATCH] Move monster waypoint handling to the client --- monsters.cfg | 1 - qcsrc/client/autocvars.qh | 2 + qcsrc/common/monsters/cl_monsters.qc | 151 ++++++++++++++++++++- qcsrc/common/monsters/monster/mage.qc | 2 +- qcsrc/common/monsters/monsters.qh | 12 +- qcsrc/common/monsters/sv_monsters.qc | 20 +-- qcsrc/server/autocvars.qh | 1 - qcsrc/server/command/cmd.qc | 7 +- qcsrc/server/command/sv_cmd.qc | 2 - qcsrc/server/mutators/gamemode_invasion.qc | 2 - 10 files changed, 163 insertions(+), 37 deletions(-) diff --git a/monsters.cfg b/monsters.cfg index 05f6fca8a..d7bd5c968 100644 --- a/monsters.cfg +++ b/monsters.cfg @@ -170,7 +170,6 @@ set g_monsters_owners 1 set g_monsters_teams 1 set g_monsters_spawnshieldtime 2 set g_monsters_typefrag 1 -set g_monsters_healthbars 1 set g_monsters_target_range 2000 set g_monsters_target_infront 0 set g_monsters_attack_range 120 diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 8175695ab..eca2961a2 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -169,6 +169,8 @@ float autocvar_g_waypointsprite_spam; float autocvar_g_waypointsprite_timealphaexponent; var float autocvar_g_waypointsprite_turrets = TRUE; var float autocvar_g_waypointsprite_turrets_maxdist = 5000; +var float autocvar_g_waypointsprite_monsters = TRUE; +var float autocvar_g_waypointsprite_monsters_maxdist = 5000; var float autocvar_hud_cursormode = TRUE; float autocvar_hud_colorflash_alpha; float autocvar_hud_configure_checkcollisions; diff --git a/qcsrc/common/monsters/cl_monsters.qc b/qcsrc/common/monsters/cl_monsters.qc index bc02a37a5..ff7e9f7ae 100644 --- a/qcsrc/common/monsters/cl_monsters.qc +++ b/qcsrc/common/monsters/cl_monsters.qc @@ -22,6 +22,151 @@ void monster_die() self.solid = SOLID_CORPSE; } +void monster_draw2d() +{ + if(self.netname == "") + return; + + if(!autocvar_g_waypointsprite_monsters) + return; + + if(autocvar_cl_hidewaypoints) + return; + + if(self.health <= 0) + return; + + float dist = vlen(self.origin - view_origin); + float t = (GetPlayerColor(player_localnum) + 1); + + vector o; + string txt; + + if(autocvar_cl_vehicles_hud_tactical) + if(dist < 10240 && t != self.team) + { + // TODO: Vehicle tactical hud + o = project_3d_to_2d(self.origin + '0 0 32'); + if(o_z < 0 + || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o_y < (vid_conheight * waypointsprite_edgeoffset_top) + || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) + return; // Dont draw wp's for monsters out of view + o_z = 0; + if(hud != HUD_NORMAL) + { + switch(hud) + { + case HUD_SPIDERBOT: + case HUD_WAKIZASHI: + case HUD_RAPTOR: + case HUD_BUMBLEBEE: + vector pz = drawgetimagesize("gfx/vehicles/vth-mover.tga") * 0.25; + drawpic(o - pz * 0.5, "gfx/vehicles/vth-mover.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL); + break; + } + } + } + + if(dist > self.maxdistance) + return; + + string spriteimage = self.netname; + float a = self.alpha * autocvar_hud_panel_fg_alpha; + vector rgb = spritelookupcolor(spriteimage, self.teamradar_color); + + + if(self.maxdistance > waypointsprite_normdistance) + a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent); + else if(self.maxdistance > 0) + a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha; + + if(rgb == '0 0 0') + { + self.teamradar_color = '1 0 0'; + print(sprintf("WARNING: sprite of name %s has no color, using red so you notice it\n", spriteimage)); + } + + txt = self.netname; + if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam) + txt = _("Spam"); + else + txt = spritelookuptext(spriteimage); + + if(autocvar_g_waypointsprite_uppercase) + txt = strtoupper(txt); + + if(a > 1) + { + rgb *= a; + a = 1; + } + + if(a <= 0) + return; + + rgb = fixrgbexcess(rgb); + + o = project_3d_to_2d(self.origin + '0 0 64'); + if(o_z < 0 + || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o_y < (vid_conheight * waypointsprite_edgeoffset_top) + || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) + return; // Dont draw wp's for monsters out of view + + o_z = 0; + + float edgedistance_min, crosshairdistance; + edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)), + (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)), + (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x, + (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y); + + float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height); + + crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) ); + + t = waypointsprite_scale * vidscale; + a *= waypointsprite_alpha; + + { + a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + } + if (edgedistance_min < waypointsprite_edgefadedistance) { + a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + } + if(crosshairdistance < waypointsprite_crosshairfadedistance) { + a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); + t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1))); + } + + draw_beginBoldFont(); + o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t); + o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt); + drawhealthbar( + o, + 0, + self.health / 255, + '0 0 0', + '0 0 0', + 0.5 * SPRITE_HEALTHBAR_WIDTH * t, + 0.5 * SPRITE_HEALTHBAR_HEIGHT * t, + SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize, + SPRITE_HEALTHBAR_BORDER * t, + 0, + rgb, + a * SPRITE_HEALTHBAR_BORDERALPHA, + rgb, + a * SPRITE_HEALTHBAR_HEALTHALPHA, + DRAWFLAG_NORMAL + ); + draw_endBoldFont(); +} + void monster_draw() { float dt; @@ -30,7 +175,7 @@ void monster_draw() self.move_time = time; if(dt <= 0) return; - + fixedmakevectors(self.angles); //movelib_groundalign4point(50, 25, 0.25, 45); setorigin(self, self.origin + self.velocity * dt); @@ -58,7 +203,11 @@ void monster_construct() self.move_time = time; self.drawmask = MASK_NORMAL; self.alpha = 1; + self.gravity = 1; self.draw = monster_draw; + self.draw2d = monster_draw2d; + self.maxdistance = autocvar_g_waypointsprite_monsters_maxdist; + self.teamradar_color = '1 0 0'; } void ent_monster() diff --git a/qcsrc/common/monsters/monster/mage.qc b/qcsrc/common/monsters/monster/mage.qc index 8bb3da3d2..f6140c661 100644 --- a/qcsrc/common/monsters/monster/mage.qc +++ b/qcsrc/common/monsters/monster/mage.qc @@ -292,7 +292,7 @@ void mage_heal() { pointparticles(particleeffectnum("healing_fx"), head.origin, '0 0 0', 1); head.health = bound(0, head.health + MON_CVAR(mage, heal_allies), head.max_health); - WaypointSprite_UpdateHealth(head.sprite, head.health); + self.SendFlags |= MSF_STATUS; } } diff --git a/qcsrc/common/monsters/monsters.qh b/qcsrc/common/monsters/monsters.qh index 0c9d4b888..b070a181c 100644 --- a/qcsrc/common/monsters/monsters.qh +++ b/qcsrc/common/monsters/monsters.qh @@ -28,12 +28,12 @@ const float MON_FLAG_SUPERMONSTER = 2048; // incredibly powerful monster #ifndef MENUQC .float anim_start_time; -float MSF_UPDATE = 2; -float MSF_STATUS = 4; -float MSF_SETUP = 8; -float MSF_ANG = 16; -float MSF_MOVE = 32; -float MSF_ANIM = 64; +float MSF_UPDATE = 2; +float MSF_STATUS = 4; +float MSF_SETUP = 8; +float MSF_ANG = 16; +float MSF_MOVE = 32; +float MSF_ANIM = 64; float MSF_FULL_UPDATE = 16777215; #endif diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 5760dad4f..f8858cd4e 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -449,7 +449,7 @@ void monster_move(float runspeed, float walkspeed, float stopspeed, float manim_ self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1); self.health = max(1, self.max_health * self.revive_progress); - if(self.sprite) WaypointSprite_UpdateHealth(self.sprite, self.health); + self.SendFlags |= MSF_STATUS; movelib_beak_simple(stopspeed); @@ -695,7 +695,7 @@ void monsters_reset() self.attack_finished_single = 0; self.moveto = self.origin; - WaypointSprite_UpdateHealth(self.sprite, self.health); + self.SendFlags |= MSF_STATUS; } float monster_send(entity to, float sf) @@ -788,8 +788,6 @@ void monster_die() self.ltime = time + 5; monster_dropitem(); - - WaypointSprite_Kill(self.sprite); if(self.weaponentity) { @@ -845,9 +843,6 @@ void monsters_damage (entity inflictor, entity attacker, float damage, float dea self.weaponentity.health -= damage; self.health -= damage; - - if(self.sprite) - WaypointSprite_UpdateHealth(self.sprite, self.health); self.dmg_time = time; @@ -867,10 +862,6 @@ void monsters_damage (entity inflictor, entity attacker, float damage, float dea if(self.health <= 0) { - // Update one more time to avoid waypoint fading without emptying healthbar - if(self.sprite) - WaypointSprite_UpdateHealth(self.sprite, 0); - if(deathtype == DEATH_KILL) self.candrop = FALSE; // killed by mobkill command @@ -939,13 +930,6 @@ void monster_spawn() if(teamplay) self.monster_attack = TRUE; // we can have monster enemies in team games - - if(autocvar_g_monsters_healthbars) - { - WaypointSprite_Spawn(strzone(strdecolorize(self.monster_name)), 0, 600, self, '0 0 1' * (self.maxs_z + 15), world, 0, self, sprite, FALSE, RADARICON_DANGER, ((self.team) ? Team_ColorRGB(self.team) : '1 0 0')); - WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); - WaypointSprite_UpdateHealth(self.sprite, self.health); - } monster_sound(self.msound_spawn, 0, FALSE); diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index adeccc73c..264d55408 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -1243,7 +1243,6 @@ float autocvar_g_monsters_miniboss_healthboost; float autocvar_g_monsters_drop_time; float autocvar_g_monsters_spawnshieldtime; float autocvar_g_monsters_teams; -float autocvar_g_monsters_healthbars; float autocvar_g_monsters_respawn_delay; float autocvar_g_monsters_respawn; float autocvar_g_touchexplode_radius; diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 68b1457fc..88801e125 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -196,7 +196,6 @@ void ClientCommand_mobedit(float request, float argc) switch(argv(1)) { - case "name": trace_ent.monster_name = strzone(strdecolorize(argv(2))); if(trace_ent.sprite) WaypointSprite_UpdateSprites(trace_ent.sprite, trace_ent.monster_name, "", ""); return; case "skin": if(trace_ent.monsterid != MON_MAGE) { trace_ent.skin = stof(argv(2)); trace_ent.SendFlags |= MSF_STATUS; } return; case "movetarget": trace_ent.monster_moveflags = stof(argv(2)); return; } @@ -206,7 +205,7 @@ void ClientCommand_mobedit(float request, float argc) case CMD_REQUEST_USAGE: { sprint(self, "\nUsage:^3 cmd mobedit [argument]\n"); - sprint(self, " Where 'argument' can be name, color or movetarget.\n"); + sprint(self, " Where 'argument' can be skin or movetarget.\n"); return; } } @@ -256,12 +255,11 @@ void ClientCommand_mobspawn(float request, float argc) case CMD_REQUEST_COMMAND: { entity e; - string tospawn, mname; + string tospawn; float moveflag; moveflag = (argv(2) ? stof(argv(2)) : 1); // follow owner if not defined tospawn = strtolower(argv(1)); - mname = argv(3); if(tospawn == "list") { @@ -295,7 +293,6 @@ void ClientCommand_mobspawn(float request, float argc) //WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 150, MOVE_NORMAL, self); e = spawnmonster(tospawn, 0, self, self, trace_endpos, FALSE, moveflag); - if(mname) e.monster_name = strzone(mname); sprint(self, strcat("Spawned ", e.monster_name, "\n")); } diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index 508dd1786..569480b5c 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -153,8 +153,6 @@ void GameCommand_butcher(float request) FOR_EACH_MONSTER(head) { - WaypointSprite_Kill(head.sprite); - if(head.weaponentity) remove(head.weaponentity); diff --git a/qcsrc/server/mutators/gamemode_invasion.qc b/qcsrc/server/mutators/gamemode_invasion.qc index 3355a7c7d..af717a138 100644 --- a/qcsrc/server/mutators/gamemode_invasion.qc +++ b/qcsrc/server/mutators/gamemode_invasion.qc @@ -68,7 +68,6 @@ float Invasion_CheckWinner() { FOR_EACH_MONSTER(head) { - WaypointSprite_Kill(head.sprite); if(head.weaponentity) remove(head.weaponentity); if(head.iceblock) remove(head.iceblock); remove(head); @@ -183,7 +182,6 @@ MUTATOR_HOOKFUNCTION(invasion_MonsterSpawn) { if(self.realowner == world) { - WaypointSprite_Kill(self.sprite); if(self.weaponentity) remove(self.weaponentity); if(self.iceblock) remove(self.iceblock); remove(self); -- 2.39.2