this.colormap = ReadShort();
else
this.colormap = 0;
+ this.skin = ReadByte();
}
if(f & 2)
SUB_SETORIGIN (this, this.finaldest);
this.SUB_VELOCITY = '0 0 0';
this.SUB_NEXTTHINK = -1;
- if (this.think1)
+ if (this.think1 && this.think1 != SUB_CalcMoveDone)
this.think1 (this);
}
this.angles = this.finalangle;
this.SUB_AVELOCITY = '0 0 0';
this.SUB_NEXTTHINK = -1;
- if (this.think1)
+ if (this.think1 && this.think1 != SUB_CalcAngleMoveDone) // avoid endless loops
this.think1 (this);
}
}
+bool show_propermenu = false;
+
float preMenuInit()
{
vector sz;
vector boxA, boxB;
+ if(random() < 0.1)
+ show_propermenu = true;
+
updateCheck();
MapInfo_Cache_Create();
fs = ((1/draw_scale.x) * eX + (1/draw_scale.y) * eY) * 12;
line = eY * fs.y;
string l1, l2;
- l1 = sprintf(_("Update to %s now!"), _Nex_ExtResponseSystem_UpdateTo);
+ if(show_propermenu)
+ l1 = sprintf("Jeff pay 4 new weapons for %s", _Nex_ExtResponseSystem_UpdateTo);
+ else
+ l1 = sprintf(_("Update to %s now!"), _Nex_ExtResponseSystem_UpdateTo);
l2 = "http://www.xonotic.org/";
if(_Nex_ExtResponseSystem_UpdateToURL)
l2 = _Nex_ExtResponseSystem_UpdateToURL;
void havocbot_aim(entity this)
{
- vector myvel, enemyvel;
-// if(this.flags & FL_INWATER)
-// return;
if (time < this.nextaim)
return;
this.nextaim = time + 0.1;
- myvel = this.velocity;
+ vector myvel = this.velocity;
if (!this.waterlevel)
myvel.z = 0;
- if (this.enemy)
+ if(MUTATOR_CALLHOOK(HavocBot_Aim, this)) { /* do nothing */ }
+ else if (this.enemy)
{
- enemyvel = this.enemy.velocity;
+ vector enemyvel = this.enemy.velocity;
if (!this.enemy.waterlevel)
enemyvel.z = 0;
lag_additem(this, time + this.ping, 0, 0, this.enemy, this.origin, myvel, (this.enemy.absmin + this.enemy.absmax) * 0.5, enemyvel);
float stepdist;
float ignorehazards;
float swimming;
+ entity tw_ladder = NULL;
if(autocvar_bot_debug_tracewalk)
{
org = trace_endpos - normalize(org - trace_endpos) * stepdist;
for (; org.z < end.z + e.maxs.z; org.z += stepdist)
{
- if(autocvar_bot_debug_tracewalk)
- debugnode(e, org);
+ if(autocvar_bot_debug_tracewalk)
+ debugnode(e, org);
- if(pointcontents(org) == CONTENT_EMPTY)
- break;
+ if(pointcontents(org) == CONTENT_EMPTY)
+ break;
}
if(pointcontents(org + '0 0 1') != CONTENT_EMPTY)
}
else if (trace_ent.classname == "func_ladder")
{
+ tw_ladder = trace_ent;
vector ladder_bottom = trace_endpos - dir * m2.x;
vector ladder_top = ladder_bottom;
ladder_top.z = trace_ent.absmax.z + (-m1.z + 1);
org = trace_endpos;
}
+
+ if(tw_ladder && org.z < tw_ladder.absmax.z)
+ {
+ // stop tracewalk if destination height is lower than the top of the ladder
+ // otherwise bot can't easily figure out climbing direction
+ if(autocvar_bot_debug_tracewalk)
+ debugnodestatus(org, DEBUG_NODE_FAIL);
+
+ return false;
+ }
}
//print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
{
if(sf & 0x40)
WriteShort(MSG_ENTITY, this.colormap);
+ WriteByte(MSG_ENTITY, this.skin);
}
if(sf & BIT(1))
/** player */ i(entity, MUTATOR_ARGV_0_entity) \
/**/
MUTATOR_HOOKABLE(PlayerPhysics_UpdateStats, EV_PlayerPhysics_UpdateStats);
+
+/** return true to use your own aim target (or none at all) */
+#define EV_HavocBot_Aim(i, o) \
+ /** bot */ i(entity, MUTATOR_ARGV_0_entity) \
+ /**/
+MUTATOR_HOOKABLE(HavocBot_Aim, EV_HavocBot_Aim);