+ if((e == world || targ == world)
+ || (!e.monster_attackfunc)
+ || (time < e.attack_finished_single)
+ ) { return; }
+
+ float targ_vlen = vlen(targ.origin - e.origin);
+
+ if(targ_vlen <= e.attack_range)
+ {
+ float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE, targ);
+ if(attack_success == 1)
+ Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
+ else if(attack_success > 0)
+ return;
+ }
+
+ if(targ_vlen > e.attack_range)
+ {
+ float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED, targ);
+ if(attack_success == 1)
+ Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
+ else if(attack_success > 0)
+ return;
+ }
+}
+
+
+// ======================
+// Main monster functions
+// ======================
+
+void Monster_UpdateModel()
+{SELFPARAM();
+ // assume some defaults
+ /*self.anim_idle = animfixfps(self, '0 1 0.01', '0 0 0');
+ self.anim_walk = animfixfps(self, '1 1 0.01', '0 0 0');
+ self.anim_run = animfixfps(self, '2 1 0.01', '0 0 0');
+ self.anim_fire1 = animfixfps(self, '3 1 0.01', '0 0 0');
+ self.anim_fire2 = animfixfps(self, '4 1 0.01', '0 0 0');
+ self.anim_melee = animfixfps(self, '5 1 0.01', '0 0 0');
+ self.anim_pain1 = animfixfps(self, '6 1 0.01', '0 0 0');
+ self.anim_pain2 = animfixfps(self, '7 1 0.01', '0 0 0');
+ self.anim_die1 = animfixfps(self, '8 1 0.01', '0 0 0');
+ self.anim_die2 = animfixfps(self, '9 1 0.01', '0 0 0');*/
+
+ // then get the real values
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_anim(mon);
+}
+
+void Monster_Touch()
+{SELFPARAM();
+ if(other == world) { return; }
+
+ if(other.monster_attack)
+ if(self.enemy != other)
+ if(!IS_MONSTER(other))
+ if(Monster_ValidTarget(self, other))
+ self.enemy = other;
+}
+
+void Monster_Miniboss_Check()
+{SELFPARAM();