case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
case ENT_CLIENT_TURRET: ent_turret(); break;
- case ENT_CLIENT_MONSTER: ent_monster(); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
../common/animdecide.qh
command/cl_cmd.qh
-../common/monsters/cl_monsters.qh
../common/monsters/monsters.qh
autocvars.qh
../common/urllib.qc
command/cl_cmd.qc
-../common/monsters/cl_monsters.qc
../common/monsters/monsters.qc
../warpzonelib/anglestransform.qc
const float ENT_CLIENT_TURRET = 40;
const float ENT_CLIENT_AUXILIARYXHAIR = 50;
const float ENT_CLIENT_VEHICLE = 60;
-const float ENT_CLIENT_MONSTER = 70;
const float SPRITERULE_DEFAULT = 0;
const float SPRITERULE_TEAMPLAY = 1;
CSQCMODEL_PROPERTY(512, float, ReadChar, WriteChar, anim_upper_action) \
CSQCMODEL_PROPERTY(512, float, ReadApproxPastTime, WriteApproxPastTime, anim_upper_time) \
CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
+ CSQCMODEL_ENDIF \
+ CSQCMODEL_IF(!isplayer) \
+ CSQCMODEL_PROPERTY(2048, float, ReadByte, WriteByte, monsterid) \
CSQCMODEL_ENDIF
// TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
+++ /dev/null
-// =========================
-// CSQC Monster Properties
-// =========================
-
-
-.vector glowmod;
-void monster_changeteam()
-{
- self.glowmod = Team_ColorRGB(self.team - 1);
-
- if(self.team)
- {
- self.teamradar_color = Team_ColorRGB(self.team - 1);
- self.colormap = 1024 + (self.team - 1) * 17;
- }
- else
- {
- self.teamradar_color = '1 0 0';
- self.colormap = 1024;
- }
-}
-
-void monster_die()
-{
- MON_ACTION(self.monsterid, MR_DEATH);
-
- self.solid = SOLID_CORPSE;
-}
-
-void monster_draw2d()
-{
- if(self.netname == "")
- return;
-
- if(!autocvar_g_waypointsprite_monsters)
- return;
-
- if(autocvar_cl_hidewaypoints)
- return;
-
- if(self.solid == SOLID_CORPSE)
- return; // re-spawning
-
- 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 1' * ((self.maxs_z + self.mins_z) * 0.5));
- 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 1' * (self.maxs_z + 15));
- 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;
-
- dt = time - self.move_time;
- 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);
- self.angles_y = self.move_angles_y;
-}
-
-void monster_construct()
-{
- entity mon = get_monsterinfo(self.monsterid);
-
- if(mon.spawnflags & MONSTER_SIZE_BROKEN)
- self.scale = 1.3;
-
- self.netname = M_NAME(self.monsterid);
-
- setorigin(self, self.origin);
- setmodel(self, mon.model);
- setsize(self, mon.mins, mon.maxs);
-
- self.move_movetype = MOVETYPE_BOUNCE;
- self.health = 255;
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- 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;
-}
-
-void ent_monster()
-{
- float sf;
- sf = ReadByte();
-
- if(sf & MSF_SETUP)
- {
- self.monsterid = ReadByte();
-
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.angles_x = ReadAngle();
- self.angles_y = ReadAngle();
-
- self.skin = ReadByte();
- self.team = ReadByte();
-
- monster_construct();
- monster_changeteam();
- }
-
- if(sf & MSF_ANG)
- {
- self.move_angles_x = ReadShort();
- self.move_angles_y = ReadShort();
- self.angles = self.move_angles;
- }
-
- if(sf & MSF_MOVE)
- {
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
- setorigin(self, self.origin);
-
- self.velocity_x = ReadShort();
- self.velocity_y = ReadShort();
- self.velocity_z = ReadShort();
-
- self.move_angles_y = ReadShort();
-
- self.move_time = time;
- self.move_velocity = self.velocity;
- self.move_origin = self.origin;
- }
-
- if(sf & MSF_ANIM)
- {
- self.frame1time = ReadCoord();
- self.frame = ReadByte();
- }
-
- if(sf & MSF_STATUS)
- {
- self.skin = ReadByte();
-
- float _tmp;
- _tmp = ReadByte();
- if(_tmp != self.team)
- {
- self.team = _tmp;
- monster_changeteam();
- }
-
- _tmp = ReadByte();
- if(_tmp == 4) // respawning
- setmodel(self, "null");
-
- _tmp = ReadByte();
-
- if(_tmp == 0 && self.health != 0)
- monster_die();
-
- self.health = _tmp;
- }
-}
+++ /dev/null
-void ent_monster();
}
case MR_DEATH:
{
- monsters_setframe(animus_anim_death);
+ self.frame = animus_anim_death;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_medium;
self.monster_attackfunc = animus_attack;
- monsters_setframe(animus_anim_stand);
+ self.frame = animus_anim_stand;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/demon.mdl");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/demon.mdl");
return TRUE;
}
case MR_DEATH:
{
- monsters_setframe((random() > 0.5) ? bruiser_anim_death1 : bruiser_anim_death2);
+ self.frame = ((random() > 0.5) ? bruiser_anim_death1 : bruiser_anim_death2);
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_armor_medium;
self.monster_attackfunc = bruiser_attack;
- monsters_setframe(bruiser_anim_stand);
+ self.frame = bruiser_anim_stand;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/knight.mdl");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/knight.mdl");
return TRUE;
self.brute_cycles = 0;
if(random() <= MON_CVAR(brute, attack_uzi_chance))
{
- monsters_setframe(brute_anim_pain);
+ self.frame = brute_anim_pain;
self.attack_finished_single = time + 0.8;
defer(0.1, brute_uzi);
}
{
monster_makevectors(self.enemy);
brute_grenade();
- monsters_setframe(brute_anim_pain);
+ self.frame = brute_anim_pain;
self.attack_finished_single = time + 1.2;
}
}
case MR_DEATH:
{
- monsters_setframe(brute_anim_die);
+ self.frame = brute_anim_die;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_bullets;
self.monster_attackfunc = brute_attack;
- monsters_setframe(brute_anim_idle);
+ self.frame = brute_anim_idle;
self.weapon = WEP_GRENADE_LAUNCHER;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
+ precache_model ("models/monsters/ogre.dpm");
precache_sound ("weapons/uzi_fire.wav");
precache_sound ("weapons/grenade_impact.wav");
precache_sound ("weapons/grenade_fire.wav");
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/ogre.dpm");
return TRUE;
{
if(self.monster_owner.flags & FL_MONSTER)
self.monster_owner = world;
- monsters_setframe(cerberus_anim_die);
+ self.frame = cerberus_anim_die;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_small;
self.monster_attackfunc = cerberus_attack;
- monsters_setframe(cerberus_anim_idle);
+ self.frame = cerberus_anim_idle;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/dog.dpm");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/dog.dpm");
return TRUE;
{
case 1:
{
- monsters_setframe(knight_anim_magic2);
+ self.frame = knight_anim_magic2;
self.attack_finished_single = time + 2;
defer(0.4, knight_fireball);
}
case 3:
{
- monsters_setframe(knight_anim_magic3);
+ self.frame = knight_anim_magic3;
self.attack_finished_single = time + 3;
defer(0.4, knight_spikes);
case MR_DEATH:
{
float chance = random();
- monsters_setframe((random() > 0.5) ? knight_anim_death1 : knight_anim_death2);
+ self.frame = ((random() > 0.5) ? knight_anim_death1 : knight_anim_death2);
if(chance < 0.10 || self.spawnflags & MONSTERFLAG_MINIBOSS)
if(self.candrop)
{
self.monster_loot = spawnfunc_item_armor_big;
self.monster_attackfunc = knight_attack;
- monsters_setframe(knight_anim_stand);
+ self.frame = knight_anim_stand;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
+ precache_model ("models/monsters/hknight.mdl");
precache_sound ("player/lava.wav");
precache_sound ("weapons/fireball2.wav");
return TRUE;
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/hknight.mdl");
return TRUE;
return FALSE;
if(vlen(e.origin - self.origin) > MON_CVAR(mage, heal_range))
return FALSE;
- if(DIFF_TEAM(e, self))
+ if(DIFF_TEAM(e, self) && e != self.monster_owner)
return FALSE;
if(e.frozen)
return FALSE;
{
pointparticles(particleeffectnum("healing_fx"), head.origin, '0 0 0', 1);
head.health = bound(0, head.health + MON_CVAR(mage, heal_allies), head.max_health);
- head.SendFlags |= MSF_STATUS;
}
}
if(washealed)
{
- monsters_setframe(mage_anim_attack);
+ self.frame = mage_anim_attack;
self.attack_finished_single = time + MON_CVAR(mage, heal_delay);
}
}
self.lastshielded = time + MON_CVAR(mage, shield_delay);
- monsters_setframe(mage_anim_attack);
+ self.frame = mage_anim_attack;
self.attack_finished_single = time + 1;
self.m_armor_blockpercent = MON_CVAR(mage, shield_blockpercent);
{
case MONSTER_ATTACK_MELEE:
{
- monsters_setframe(mage_anim_attack);
+ self.frame = mage_anim_attack;
self.attack_finished_single = time + MON_CVAR(mage, attack_melee_delay);
defer(0.2, mageattack_melee);
return TRUE;
}
- monsters_setframe(mage_anim_attack);
+ self.frame = mage_anim_attack;
self.attack_finished_single = time + MON_CVAR(mage, attack_spike_delay);
defer(0.2, mage_spike);
}
case MR_DEATH:
{
- monsters_setframe(mage_anim_death);
+ self.frame = mage_anim_death;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_large;
self.monster_attackfunc = mage_attack;
- monsters_setframe(mage_anim_walk);
+ self.frame = mage_anim_walk;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
+ precache_model ("models/monsters/mage.dpm");
precache_model ("models/items/g_h50.md3");
precache_model ("models/ctf/shield.md3");
precache_sound ("weapons/grenade_impact.wav");
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/mage.dpm");
return TRUE;
void shambler_delayedsmash()
{
- monsters_setframe(shambler_anim_smash);
+ self.frame = shambler_anim_smash;
defer(0.7, shambler_smash);
self.attack_finished_single = time + 1.1;
}
}
case MONSTER_ATTACK_RANGED:
{
- monsters_setframe(shambler_anim_magic);
+ self.frame = shambler_anim_magic;
self.attack_finished_single = time + 1.1;
defer(0.6, CastLightning);
}
case MR_DEATH:
{
- monsters_setframe(shambler_anim_death);
+ self.frame = shambler_anim_death;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_mega;
self.monster_attackfunc = shambler_attack;
- monsters_setframe(shambler_anim_stand);
+ self.frame = shambler_anim_stand;
self.weapon = WEP_NEX;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/shambler.mdl");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/shambler.mdl");
return TRUE;
self.enemy = world;
self.health = 0;
- self.SendFlags |= MSF_MOVE | MSF_STATUS;
-
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_rockets;
self.monster_attackfunc = slime_attack;
- monsters_setframe(slime_anim_idle);
+ self.frame = slime_anim_idle;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
+ precache_model ("models/monsters/slime.dpm");
precache_sound ("weapons/rocket_impact.wav");
return TRUE;
}
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/slime.dpm");
return TRUE;
if(self.enemy.frozen)
return FALSE;
- monsters_setframe(spider_anim_attack2);
+ self.frame = spider_anim_attack2;
self.attack_finished_single = time + MON_CVAR(spider, attack_web_delay);
spider_shootweb(self.spider_type);
}
case MR_DEATH:
{
- monsters_setframe(spider_anim_attack);
+ self.frame = spider_anim_attack;
self.angles_x = 180;
- self.SendFlags |= MSF_ANG;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_medium;
self.monster_attackfunc = spider_attack;
- monsters_setframe(spider_anim_idle);
+ self.frame = spider_anim_idle;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
+ precache_model ("models/monsters/spider.dpm");
precache_model ("models/ice/ice.md3");
precache_sound ("weapons/electro_fire2.wav");
precache_sound ("weapons/fireball_fire.wav");
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/spider.dpm");
return TRUE;
}
case MR_DEATH:
{
- monsters_setframe(stingray_anim_death);
+ self.frame = stingray_anim_death;
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_small;
self.monster_attackfunc = stingray_attack;
- monsters_setframe(stingray_anim_swim);
+ self.frame = stingray_anim_swim;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/fish.mdl");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/fish.mdl");
return TRUE;
}
case MR_DEATH:
{
- monsters_setframe(wyvern_anim_death);
+ self.frame = wyvern_anim_death;
self.velocity_x = -200 + 400 * random();
self.velocity_y = -200 + 400 * random();
self.velocity_z = 100 + 100 * random();
self.monster_loot = spawnfunc_item_cells;
self.monster_attackfunc = wyvern_attack;
- monsters_setframe(wyvern_anim_hover);
+ self.frame = wyvern_anim_hover;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/wizard.mdl");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/wizard.mdl");
return TRUE;
if(self.health <= 0)
return;
- monsters_setframe(zombie_anim_blockend);
+ self.frame = zombie_anim_blockend;
self.armorvalue = 0;
self.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent;
}
float zombie_block()
{
- monsters_setframe(zombie_anim_blockstart);
+ self.frame = zombie_anim_blockstart;
self.armorvalue = 100;
self.m_armor_blockpercent = 0.9;
self.state = MONSTER_STATE_ATTACK_MELEE; // freeze monster
{
self.armorvalue = 0;
self.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent;
- monsters_setframe((random() > 0.5) ? zombie_anim_deathback1 : zombie_anim_deathfront1);
+ self.frame = ((random() > 0.5) ? zombie_anim_deathback1 : zombie_anim_deathfront1);
return TRUE;
}
case MR_SETUP:
self.monster_loot = spawnfunc_item_health_medium;
self.monster_attackfunc = zombie_attack;
- monsters_setframe(zombie_anim_spawn);
+ self.frame = zombie_anim_spawn;
self.spawn_time = time + 2.1;
self.spawnshieldtime = self.spawn_time;
self.respawntime = 0.2;
return TRUE;
}
- case MR_INIT:
+ case MR_PRECACHE:
{
- // nothing
+ precache_model ("models/monsters/zombie.dpm");
return TRUE;
}
case MR_CONFIG:
{
switch(req)
{
- case MR_DEATH:
- {
- // nothing
- return TRUE;
- }
- case MR_INIT:
+ case MR_PRECACHE:
{
precache_model ("models/monsters/zombie.dpm");
return TRUE;
e.model = strzone(strcat("models/monsters/", modelname));
#ifndef MENUQC
- func(MR_INIT);
+ func(MR_PRECACHE);
#endif
}
float m_null(float dummy) { return 0; }
// monster requests
#define MR_SETUP 1 // (SERVER) setup monster data
#define MR_THINK 2 // (SERVER) logic to run every frame
-#define MR_DEATH 3 // (BOTH) called when monster dies
-#define MR_INIT 4 // (BOTH) precaches models/sounds used by this monster
+#define MR_DEATH 3 // (SERVER) called when monster dies
+#define MR_PRECACHE 4 // (BOTH) precaches models/sounds used by this monster
#define MR_CONFIG 5 // (ALL)
// functions:
.float spawnflags;
.vector mins, maxs; // monster hitbox size
-// csqc linking
-#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_FULL_UPDATE = 16777215;
-#endif
-
// other useful macros
#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
#define M_NAME(monstertype) (get_monsterinfo(monstertype)).monster_name
self.gravity = 1;
self.velocity = randomvec() * 175 + '0 0 325';
self.classname = "droppedweapon"; // hax
+ self.wait = time + 0.7;
SUB_SetFade(self, time + autocvar_g_monsters_drop_time, 1);
}
}
}
-void monsters_setframe(float _frame)
-{
- if(self.frame == _frame)
- return;
-
- self.anim_start_time = time;
- self.frame = _frame;
- self.SendFlags |= MSF_ANIM;
-}
-
float monster_isvalidtarget (entity targ, entity ent)
{
if(!targ || !ent)
self.velocity_x = 0;
self.velocity_y = 0;
self.state = MONSTER_STATE_ATTACK_MELEE;
- self.SendFlags |= MSF_MOVE;
}
- monsters_setframe(anim);
+ self.frame = anim;
if(anim_finished != 0)
self.attack_finished_single = time + anim_finished;
if ((self.spawnflags & MONSTERFLAG_MINIBOSS) || (chance < autocvar_g_monsters_miniboss_chance))
{
self.health += autocvar_g_monsters_miniboss_healthboost;
+ self.effects |= EF_RED;
if not(self.weapon)
self.weapon = WEP_NEX;
}
setorigin(self, self.pos1);
self.angles = self.pos2;
self.health = self.max_health;
-
- self.SendFlags |= MSF_MOVE;
- self.SendFlags |= MSF_STATUS;
+ setmodel(self, "null");
}
else
{
if(!Monster_CanJump(vel))
return FALSE;
- monsters_setframe(anm);
+ self.frame = anm;
self.state = MONSTER_STATE_ATTACK_LEAP;
self.touch = touchfunc;
self.origin_z += 1;
{
self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1);
self.health = max(1, self.max_health * self.revive_progress);
-
- self.SendFlags |= MSF_STATUS;
-
+
movelib_beak_simple(stopspeed);
- monsters_setframe(manim_idle);
+ self.frame = manim_idle;
self.enemy = world;
self.nextthink = time + self.ticrate;
if(self.revive_progress >= 1)
Unfreeze(self); // wait for next think before attacking
- // don't bother updating angles here?
- if(self.origin != self.oldorigin)
- {
- self.oldorigin = self.origin;
- self.SendFlags |= MSF_MOVE;
- }
-
return; // no moving while frozen
}
self.movetype = MOVETYPE_BOUNCE;
//self.velocity_z = -200;
- self.SendFlags |= MSF_MOVE | MSF_ANG;
-
return;
}
else if(self.fish_wasdrowning)
{
runspeed = walkspeed = 0;
if(time >= self.spawn_time)
- monsters_setframe(manim_idle);
+ self.frame = manim_idle;
movelib_beak_simple(stopspeed);
- if(self.oldorigin != self.origin)
- {
- self.oldorigin = self.origin;
- self.SendFlags |= MSF_MOVE;
- }
return;
}
if(time > self.pain_finished)
if(time > self.attack_finished_single)
if(vlen(self.velocity) > 10)
- monsters_setframe((self.enemy) ? manim_run : manim_walk);
+ self.frame = ((self.enemy) ? manim_run : manim_walk);
else
- monsters_setframe(manim_idle);
+ self.frame = manim_idle;
}
else
{
if(time > self.attack_finished_single)
if(time > self.pain_finished)
if (vlen(self.velocity) <= 30)
- monsters_setframe(manim_idle);
+ self.frame = manim_idle;
}
monster_checkattack(self, self.enemy);
-
- if(self.angles != self.oldangles)
- {
- self.oldangles = self.angles;
- self.SendFlags |= MSF_ANG;
- }
-
- if(self.origin != self.oldorigin)
- {
- self.oldorigin = self.origin;
- self.SendFlags |= MSF_MOVE;
- }
}
void monster_dead_think()
Monster_Fade();
return;
}
-
- if(self.oldorigin != self.origin)
- {
- self.oldorigin = self.origin;
- self.SendFlags |= MSF_MOVE;
- }
+
+ CSQCMODEL_AUTOUPDATE();
}
void monsters_setstatus()
self.goalentity = world;
self.attack_finished_single = 0;
self.moveto = self.origin;
-
- self.SendFlags |= MSF_STATUS;
-}
-
-float monster_send(entity to, float sf)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_MONSTER);
- WriteByte(MSG_ENTITY, sf);
- if(sf & MSF_SETUP)
- {
- WriteByte(MSG_ENTITY, self.monsterid);
-
- WriteCoord(MSG_ENTITY, self.origin_x);
- WriteCoord(MSG_ENTITY, self.origin_y);
- WriteCoord(MSG_ENTITY, self.origin_z);
-
- WriteAngle(MSG_ENTITY, self.angles_x);
- WriteAngle(MSG_ENTITY, self.angles_y);
-
- WriteByte(MSG_ENTITY, self.skin);
- WriteByte(MSG_ENTITY, self.team);
- }
-
- if(sf & MSF_ANG)
- {
- WriteShort(MSG_ENTITY, rint(self.angles_x));
- WriteShort(MSG_ENTITY, rint(self.angles_y));
- }
-
- if(sf & MSF_MOVE)
- {
- WriteShort(MSG_ENTITY, rint(self.origin_x));
- WriteShort(MSG_ENTITY, rint(self.origin_y));
- WriteShort(MSG_ENTITY, rint(self.origin_z));
-
- WriteShort(MSG_ENTITY, rint(self.velocity_x));
- WriteShort(MSG_ENTITY, rint(self.velocity_y));
- WriteShort(MSG_ENTITY, rint(self.velocity_z));
-
- WriteShort(MSG_ENTITY, rint(self.angles_y));
- }
-
- if(sf & MSF_ANIM)
- {
- WriteCoord(MSG_ENTITY, self.anim_start_time);
- WriteByte(MSG_ENTITY, self.frame);
- }
-
- if(sf & MSF_STATUS)
- {
- WriteByte(MSG_ENTITY, self.skin);
-
- WriteByte(MSG_ENTITY, self.team);
-
- WriteByte(MSG_ENTITY, self.deadflag);
-
- if(self.health <= 0)
- WriteByte(MSG_ENTITY, 0);
- else
- WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255));
- }
-
- return TRUE;
-}
-
-void monster_link(void() spawnproc)
-{
- Net_LinkEntity(self, TRUE, 0, monster_send);
- self.think = spawnproc;
- self.nextthink = time;
}
void monsters_corpse_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
if not(self.flags & FL_FLY)
self.velocity = '0 0 0';
- self.SendFlags |= MSF_MOVE;
-
// number of monsters spawned with mobspawn command
totalspawned -= 1;
vector v;
float take, save;
- v = healtharmor_applydamage(self.armorvalue, self.m_armor_blockpercent, damage, deathtype);
+ v = healtharmor_applydamage(self.armorvalue, self.m_armor_blockpercent, deathtype, damage);
take = v_x;
save = v_y;
self.health -= take;
+
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
self.dmg_time = time;
monster_die(attacker);
+ WaypointSprite_Kill(self.sprite);
+
frag_attacker = attacker;
frag_target = self;
MUTATOR_CALLHOOK(MonsterDies);
self.nextthink = time + 0.1;
}
}
-
- self.SendFlags |= MSF_STATUS;
}
void monster_think()
}
MON_ACTION(self.monsterid, MR_THINK);
+
+ CSQCMODEL_AUTOUPDATE();
}
void monster_spawn()
self.max_health = self.health;
self.pain_finished = self.nextthink;
- self.anim_start_time = time;
-
- if not(self.noalign)
- {
- setorigin(self, self.origin + '0 0 20');
- tracebox(self.origin + '0 0 100', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
- setorigin(self, trace_endpos);
- }
+
+ if(IS_PLAYER(self.monster_owner))
+ self.effects |= EF_DIMLIGHT;
if not(self.monster_respawned)
if not(self.skin)
if not(self.attack_range)
self.attack_range = autocvar_g_monsters_attack_range;
-
- self.pos1 = self.origin;
-
- //monster_setupsounds(self.netname);
+
precache_monstersounds();
UpdateMonsterSounds();
- //monster_precachesounds(self);
if(teamplay)
self.monster_attack = TRUE; // we can have monster enemies in team games
MonsterSound(monstersound_spawn, 0, FALSE, CH_VOICE);
+
+ WaypointSprite_Spawn(M_NAME(self.monsterid), 0, 1024, self, '0 0 1' * (self.maxs_z + 15), world, self.team, self, sprite, TRUE, RADARICON_DANGER, ((self.team) ? Team_ColorRGB(self.team) : '1 0 0'));
+ WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
self.think = monster_think;
self.nextthink = time + self.ticrate;
- self.SendFlags |= MSF_SETUP;
-
MUTATOR_CALLHOOK(MonsterSpawn);
}
if not(self.monster_respawned)
monsters_total += 1;
+ setmodel(self, mon.model);
setsize(self, mon.mins, mon.maxs);
self.flags = FL_MONSTER;
self.takedamage = DAMAGE_AIM;
self.enemy = world;
self.velocity = '0 0 0';
self.moveto = self.origin;
+ self.pos1 = self.origin;
self.pos2 = self.angles;
self.reset = monsters_reset;
self.netname = mon.netname;
self.spawn_time = time;
self.gravity = 1;
self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_BOTCLIP | DPCONTENTS_MONSTERCLIP;
+
+ if(autocvar_g_fullbrightplayers)
+ self.effects |= EF_FULLBRIGHT;
+
+ if(autocvar_g_nodepthtestplayers)
+ self.effects |= EF_NODEPTHTEST;
if(mon.spawnflags & MONSTER_TYPE_SWIM)
self.flags |= FL_SWIM;
if not(self.monster_moveflags)
self.monster_moveflags = MONSTER_MOVE_WANDER;
-
- monster_link(monster_spawn);
+
+ if not(self.noalign)
+ {
+ setorigin(self, self.origin + '0 0 20');
+ tracebox(self.origin + '0 0 64', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
+ setorigin(self, trace_endpos);
+ }
+
+ monster_spawn();
+
+ CSQCMODEL_AUTOINIT();
return TRUE;
}
#undef CSQCMODEL_IF
if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
+ {
setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
// FIXME do we WANT this to override mins/maxs?
+ if(isplayer)
+ setsize(self, PL_MIN, PL_MAX);
+ else if(self.monsterid)
+ {
+ entity mon = get_monsterinfo(self.monsterid);
+ setsize(self, mon.mins, mon.maxs);
+ }
+ }
if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
{
switch(argv(1))
{
- case "skin": if(trace_ent.monsterid != MON_MAGE) { trace_ent.skin = stof(argv(2)); trace_ent.SendFlags |= MSF_STATUS; } return;
+ case "skin": if(trace_ent.monsterid != MON_MAGE) { trace_ent.skin = stof(argv(2)); } return;
case "movetarget": trace_ent.monster_moveflags = stof(argv(2)); return;
}
}
if(head.iceblock)
remove(head.iceblock);
+ WaypointSprite_Kill(head.sprite);
+
remove(head);
++removed_count;
}
{
if(head.weaponentity) remove(head.weaponentity);
if(head.iceblock) remove(head.iceblock);
+ WaypointSprite_Kill(head.sprite);
remove(head);
}
{
if(self.weaponentity) remove(self.weaponentity);
if(self.iceblock) remove(self.iceblock);
+ WaypointSprite_Kill(self.sprite);
remove(self);
return FALSE;
}
entity e = find(world, targetname, self.target);
if (e != world)
self.team = e.team;
-
- self.SendFlags |= MSF_STATUS; // update team
return FALSE;
}
if(e != world)
{
self.team = e.team;
- self.SendFlags |= MSF_STATUS;
ee = e;
}
}
return;
if (self.owner == other)
return;
+ if (time < self.wait)
+ return;
switch(MUTATOR_CALLHOOK(ItemTouch))
{