About Pushable Models
#3524 posted by
ranger on 2024/12/29 16:50:52
"MOVETYPE_PUSH with a non bsp model" is this fixable?
So if I make monster corpses pushable it will cause this error?
I know shubnigurrath caused this sometimes...
Who Is Pushing
#3525 posted by
Preach on 2024/12/29 20:25:29
I think you misunderstand MOVETYPE_PUSH. It's not to make a thing be pushable, it's designed for things like doors and platforms that
do the pushing. Don't make corpses MOVETYPE_PUSH, or anything else that isn't a BSP object for that matter.
Yes, the teleport train is MOVETYPE_PUSH without being a BSP object, but that's why it sometimes crashes! It was a bad idea, probably done in a hurry to get Quake out of the door.
You can read some more on the issue here, but bear in mind that the fix discussed on the page is an engine-level fix. If you're writing a mod that doesn't prescribe which engine to use, you can't benefit from this.
https://www.quake-info-pool.net/q1/qfix.htm#movetype_push
Proximity Mine Help (based Off SoA Prox Launcher Code)
#3526 posted by
ranger on 2024/12/30 17:19:16
Basically it's overall working but
the key issues are
it never seems to stick on world (it otherwise behaves properly more or less), and thus the arming and stick sounds never play. Also even if it doesn't stick the arming sound never plays
besides that it properly triggers on enemies, bounces off doors & enemies etc, and works more or less...
I've been working on this for 9+h and can't figure it out!
void() ProximityBomb =
{
local entity head;
local float blowup;
if (vlen(self.spawnmaster.velocity)>0)
{
ProximityGrenadeExplode();
self.think();
return;
}
if (time > self.delay)
{
mine_disarm();
self.think();
return;
}
self.touch = SUB_Null; //new
self.owner = world;
self.takedamage = DAMAGE_YES;
head = findradius(self.origin, PROX_MINE_RADIUS); //sensor radius
blowup = 0;
while (head) //what to look for
{
// Don't detonate on players or other mines
if ((head != self) && (head.health > 0) && (head.flags & (FL_CLIENT|FL_MONSTER)) && (head.classname != self.classname) && (head != self.lastvictim)) //(head.classname != "player"))
{
blowup = 1;
}
traceline(self.origin,head.origin,TRUE,self);
if (trace_fraction != 1.0)
blowup = 0;
if (blowup==1)
{
ProximityGrenadeExplode();
self.nextthink = time + 0.5;
return;
}
head = head.chain;
}
self.nextthink = time + 0.25;
};
#3527 posted by
ranger on 2024/12/30 17:19:52
void() ProximityArmed = //new
{
sound(self, CHAN_WEAPON, "weapons/proxarmed.wav", 1, ATTN_NORM);
self.think = ProximityBomb;
self.nextthink = time + 0.25;
};
void() ProximityGrenadeTouch =
{
if (other == self || other == self.owner) //|| other == self.owner
{
sound (self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
return;
}
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// Don't collide with other mines
if (other.classname == self.classname)
{
sound (self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_BOUNCE; // Add this line
return;
}
// Check if it's a brush entity (like doors)
if (other.movetype == MOVETYPE_PUSH) //|| other.solid == SOLID_BSP
{
sound(self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_BOUNCE; // Add this line
return;
}
if (other.flags & FL_CLIENT) //user disarm mine
{
//self.solid = SOLID_NOT;
mine_disarm();
//remove(self);
return;
}
if ((other.takedamage == DAMAGE_AIM || other.solid == SOLID_TRIGGER || other.flags & FL_MONSTER )) //don't det on monsters || other.flags & FL_CLIENT
{
sound(self, CHAN_WEAPON, "weapons/proxbounce.wav", 1, ATTN_NORM);
//self.movetype = MOVETYPE_BOUNCE;
T_Damage(other, self, self.owner, 1);
//self.think();
return;
}
self.movetype = MOVETYPE_TOSS;
if (self.state == 1)
return;
if (vlen(other.velocity) > 0)
{
ProximityGrenadeExplode();
self.think();
return;
}
else
{
sound (self, CHAN_WEAPON, "weapons/proxstick.wav", 1, ATTN_NORM); // bounce sound
self.movetype = MOVETYPE_NONE;
setsize (self, '-5 -5 -5', '5 5 5');
self.state = 1;
self.spawnmaster = other;
self.velocity = '0 0 0';
// Start arming sequence
self.think = ProximityArmed;
self.nextthink = time + 2;
self.touch = SUB_Null; //new
self.solid = SOLID_NOT; //new
}
};
#3528 posted by
ranger on 2024/12/30 17:20:49
void() ThrowProxMine =
{
float x;
// Check if enough time has passed since last throw
if (self.last_mine_time > time - 1.5)
return;
// Check if player has enough ammo
if (self.ammo_rockets2 < 1)
local entity missile; //, mpuff;
self.currentammo = self.ammo_rockets2 = self.ammo_rockets2 - 1;
self.last_mine_time = time; // Update last throw time
sound (self, CHAN_BODY, "zombie/z_shot1.wav", 0.8, ATTN_STATIC);
self.punchangle_x = -2;
missile = spawn ();
missile.owner = self;
missile.lastvictim = self;
missile.movetype = MOVETYPE_TOSS;// MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
missile.classname = "proximity_mine";
missile.takedamage = DAMAGE_YES; //DAMAGE_NO;
missile.health = 2;
missile.state = 0; //not armed
// set missile speed
makevectors (self.v_angle);
if (self.v_angle_x)
missile.velocity = v_forward*400 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
missile.velocity = aim(self, 10000);
missile.velocity = missile.velocity * 400;
missile.velocity_z = 200;
}
missile.avelocity = '100 400 100';
missile.angles = vectoangles(missile.velocity);
missile.touch = ProximityGrenadeTouch;
// set missile duration
missile.nextthink = time + 2; //min time until mine can explode from enemy
missile.think = ProximityBomb; //arm
missile.th_die = ProximityGrenadeExplode;
missile.delay = time + 90; // time until mine auto disarms
setmodel (missile, "progs/proxmine.mdl");
setorigin (missile, (self.origin) + (v_forward * 0) + (v_right * -17) + '0 0 10');
setsize (missile, '-4 -4 -4', '4 4 4');
};
Debugging
#3529 posted by
Preach on 2024/12/31 08:58:58
The difficult part with your ProximityGrenadeTouch function is there are so many return statements which MIGHT end the function, and the bit of code that makes it stick to the wall is at the very end.
I would recommend you add some dprint statements to the function after each "checkpoint" - each place where the function has avoided a branch that contains a return. Then you can check how far execution gets through the function when you throw one against a wall, and deduce which exit is being taken unexpectedly. Two tips
a) pull down the console as soon as the bomb hits a wall for the first time, as you'll get a huge pile of debug messages if you let it bounce all over the shop first
b) remove the debug statements once you have solved the mystery, or they will be a pain in future