From fd6bb1c0e05c5545082e971b3c741171fa5f3b87 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 19 Apr 2015 16:24:20 +1000 Subject: [PATCH] Add the framework for a "goomba" type monster (for sidescrolling levels) --- qcsrc/common/monsters/all.qh | 1 + qcsrc/common/monsters/monster/goomba.qc | 98 +++++++++++++++++++++++++ qcsrc/common/monsters/sv_monsters.qc | 61 ++++++++++++++- qcsrc/common/monsters/sv_monsters.qh | 3 + qcsrc/server/cl_client.qc | 12 ++- 5 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 qcsrc/common/monsters/monster/goomba.qc diff --git a/qcsrc/common/monsters/all.qh b/qcsrc/common/monsters/all.qh index ec47d753e..2228dbbec 100644 --- a/qcsrc/common/monsters/all.qh +++ b/qcsrc/common/monsters/all.qh @@ -9,6 +9,7 @@ #include "monster/zombie.qc" #include "monster/spider.qc" #include "monster/mage.qc" +#include "monster/goomba.qc" #ifndef MONSTERS_EXTRA #include "monster/wyvern.qc" #endif diff --git a/qcsrc/common/monsters/monster/goomba.qc b/qcsrc/common/monsters/monster/goomba.qc new file mode 100644 index 000000000..56f635121 --- /dev/null +++ b/qcsrc/common/monsters/monster/goomba.qc @@ -0,0 +1,98 @@ +#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 diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 6b909dc72..eb41030cb 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -1113,6 +1113,62 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, float death } } +// 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; @@ -1127,9 +1183,8 @@ void 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(); } diff --git a/qcsrc/common/monsters/sv_monsters.qh b/qcsrc/common/monsters/sv_monsters.qh index f65ba001e..7a875f056 100644 --- a/qcsrc/common/monsters/sv_monsters.qh +++ b/qcsrc/common/monsters/sv_monsters.qh @@ -30,6 +30,7 @@ int monsters_killed; .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)) @@ -82,6 +83,8 @@ void monster_setupcolors(entity mon); 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); diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 913967c55..1a5876672 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -484,7 +484,13 @@ void PlayerTouch (void) 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) @@ -496,7 +502,7 @@ void PlayerTouch (void) 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); @@ -808,7 +814,7 @@ void PutClientInServer (void) self.weaponname = ""; self.switchingweapon = 0; - if(autocvar_g_player_crush) + //if(autocvar_g_player_crush) self.touch = PlayerTouch; if(!warmup_stage) -- 2.39.2