#include "monster/zombie.qc"
#include "monster/spider.qc"
#include "monster/mage.qc"
+#include "monster/goomba.qc"
#ifndef MONSTERS_EXTRA
#include "monster/wyvern.qc"
#endif
--- /dev/null
+#ifdef REGISTER_MONSTER
+REGISTER_MONSTER(
+/* MON_##id */ GOOMBA,
+/* functions */ M_Goomba, M_Goomba_Attack,
+/* spawnflags */ MON_FLAG_MELEE,
+/* mins,maxs */ '-18 -18 -20', '18 18 20',
+/* model */ "goomba.md3",
+/* netname */ "goomba",
+/* fullname */ _("Goomba")
+);
+
+#else
+#ifdef SVQC
+
+float autocvar_g_monster_goomba_health = 50;
+float autocvar_g_monster_goomba_damageforcescale = 0.1;
+float autocvar_g_monster_goomba_attack_bite_damage = 50;
+float autocvar_g_monster_goomba_speed_stop = 100;
+float autocvar_g_monster_goomba_speed_walk = 150;
+bool autocvar_g_monster_goomba_allow_jumpoff = true;
+
+void M_Goomba_Touch()
+{
+ if(!other.takedamage)
+ return;
+ if(!other.iscreature)
+ return;
+ if(time < self.attack_finished_single)
+ return;
+ if(other.monsterid == self.monsterid)
+ return; // friendly
+
+ vector vdir = normalize(other.origin - self.origin);
+ if(vdir_z <= 0.7)
+ {
+ Damage(other, self, self, autocvar_g_monster_goomba_attack_bite_damage, DEATH_MONSTER_ZOMBIE_MELEE, other.origin, '0 0 0');
+ self.attack_finished_single = time + 0.55;
+ }
+}
+
+bool M_Goomba_Attack(int attack_type)
+{
+ switch(attack_type)
+ {
+ case MONSTER_ATTACK_MELEE:
+ case MONSTER_ATTACK_RANGED:
+ {
+ // goomba has no actual attacks, it just runs into players
+ return false;
+ }
+ }
+
+ return false;
+}
+
+void spawnfunc_monster_goomba() { Monster_Spawn(MON_GOOMBA); }
+
+bool M_Goomba(int req)
+{
+ switch(req)
+ {
+ case MR_THINK:
+ {
+ Monster_Move_2D(self.speed, autocvar_g_monster_goomba_allow_jumpoff, 0, 0);
+ return false; // funny handler here, false means don't do regular moving
+ }
+ case MR_PAIN:
+ {
+ self.pain_finished = time + 0.5;
+
+ setmodel(self, self.mdl_dead);
+ return true;
+ }
+ case MR_SETUP:
+ {
+ if(!self.health) self.health = (autocvar_g_monster_goomba_health);
+ if(!self.speed) { self.speed2 = self.speed = (autocvar_g_monster_goomba_speed_walk); }
+ if(!self.stopspeed) { self.stopspeed = (autocvar_g_monster_goomba_speed_stop); }
+ if(!self.damageforcescale) { self.damageforcescale = (autocvar_g_monster_goomba_damageforcescale); }
+ if(!self.mdl_dead) { self.mdl_dead = self.mdl; }
+
+ precache_model(self.mdl_dead);
+
+ self.touch = M_Goomba_Touch;
+
+ return true;
+ }
+ case MR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#endif // REGISTER_MONSTER
}
}
+// don't check for enemies, just keep walking in a straight line
+void Monster_Move_2D(float mspeed, float allow_jumpoff, float manim_walk, float manim_idle)
+{
+ if(gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || self.draggedby != world || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < self.spawn_time)
+ {
+ mspeed = 0;
+ if(time >= self.spawn_time)
+ self.frame = manim_idle;
+ movelib_beak_simple(0.6);
+ return;
+ }
+
+ float reverse = FALSE;
+ vector a, b;
+
+ makevectors(self.angles);
+ a = self.origin + '0 0 16';
+ b = self.origin + '0 0 16' + v_forward * 32;
+
+ traceline(a, b, MOVE_NORMAL, self);
+
+ if(trace_fraction != 1.0)
+ {
+ reverse = TRUE;
+
+ if(trace_ent)
+ if(IS_PLAYER(trace_ent) && !(trace_ent.items & IT_STRENGTH))
+ reverse = FALSE;
+ }
+
+ // TODO: fix this... tracing is broken if the floor is thin
+ /*
+ if(!allow_jumpoff)
+ {
+ a = b - '0 0 32';
+ traceline(b, a, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1.0)
+ reverse = TRUE;
+ } */
+
+ if(reverse)
+ {
+ self.angles_y = anglemods(self.angles_y - 180);
+ makevectors(self.angles);
+ }
+
+ movelib_move_simple_gravity(v_forward, mspeed, 1);
+
+ if(time > self.pain_finished)
+ if(time > self.attack_finished_single)
+ if(vlen(self.velocity) > 10)
+ self.frame = manim_walk;
+ else
+ self.frame = manim_idle;
+}
+
void Monster_Think()
{
self.think = Monster_Think;
if(self.skin != self.oldskin) { Monster_Skin_Check(); }
- MON_ACTION(self.monsterid, MR_THINK);
-
- Monster_Move(self.speed2, self.speed, self.stopspeed, self.m_anim_run, self.m_anim_walk, self.m_anim_idle);
+ if(MON_ACTION(self.monsterid, MR_THINK))
+ Monster_Move(self.speed2, self.speed, self.stopspeed, self.m_anim_run, self.m_anim_walk, self.m_anim_idle);
CSQCMODEL_AUTOUPDATE();
}
.int m_anim_walk;
.int m_anim_idle;
.int oldskin;
+.string mdl_dead; // dead model for goombas
#define MONSTER_SKILLMOD(mon) (0.5 + mon.monster_skill * ((1.2 - 0.3) / 10))
void Monster_Touch();
+void Monster_Move_2D(float mspeed, float allow_jumpoff, float manim_walk, float manim_idle);
+
void Monster_Delay(float repeat_count, float repeat_defer, float defer_amnt, void() func);
float Monster_Attack_Melee(entity targ, float damg, float anim, float er, float animtime, float deathtype, float dostop);
if(other == world)
return;
- if(!IS_PLAYER(self) || !IS_PLAYER(other))
+ if(!autocvar_g_player_crush && !IS_MONSTER(other))
+ return;
+
+ if(!IS_PLAYER(self))
+ return;
+
+ if(!IS_PLAYER(other) && !IS_MONSTER(other))
return;
if(self.deadflag != DEAD_NO || other.deadflag != DEAD_NO)
if(forbidWeaponUse(self))
return;
- if(autocvar_g_player_crush_simple)
+ if(autocvar_g_player_crush_simple && IS_PLAYER(other))
{
vector vdir = normalize(other.origin - self.origin);
self.weaponname = "";
self.switchingweapon = 0;
- if(autocvar_g_player_crush)
+ //if(autocvar_g_player_crush)
self.touch = PlayerTouch;
if(!warmup_stage)