]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add the framework for a "goomba" type monster (for sidescrolling levels)
authorMario <zacjardine@y7mail.com>
Sun, 19 Apr 2015 06:24:20 +0000 (16:24 +1000)
committerMario <zacjardine@y7mail.com>
Sun, 19 Apr 2015 06:24:20 +0000 (16:24 +1000)
qcsrc/common/monsters/all.qh
qcsrc/common/monsters/monster/goomba.qc [new file with mode: 0644]
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/monsters/sv_monsters.qh
qcsrc/server/cl_client.qc

index ec47d753e7438a8c0b16d751a80407c32f5b6630..2228dbbecd313f1481599fb3431287993126cc09 100644 (file)
@@ -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 (file)
index 0000000..56f6351
--- /dev/null
@@ -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
index 6b909dc72ee7f1549bc844d01a95eb22cf4e3174..eb41030cb854a75e8eec410f372c47466353fbb1 100644 (file)
@@ -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();
 }
index f65ba001eaa17e4a7db5b720b2aa5d0264d6e99a..7a875f056568e031d22245d0fe282a31697d6c3f 100644 (file)
@@ -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);
index 913967c55f7dda12f08528a16930d75a7341eb29..1a58766728300f8a6cc449bae5d82a92a3d56386 100644 (file)
@@ -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)