BTSV_API void BT_CheckFirePadBoxTrigger(btEntity self) { vec3 mins, maxs; mins=v3add(self->mins, vec3(-8,-8,-8)); maxs=v3add(self->maxs, vec3( 8, 8, 8)); BT_CheckFireBBoxTrigger(self, mins, maxs); }
BTSV_API void BT_CheckFireBBoxTrigger(btEntity self, vec3 mins, vec3 maxs) { btEntity tmpArr[256]; btEntity lst, cur, nxt; vec3 amins, amaxs; int i, n; amins=v3add(self->origin, mins); amaxs=v3add(self->origin, maxs); lst=BT_CheckBoxEnts(amins, amaxs, BT_TRACE_TRIGGER, self); cur=lst; n=0; n=0; while(cur) { tmpArr[n++]=cur; cur=cur->chain; } for(i=0; i<n; i++) { if(btEntityP(tmpArr[i])) btEntTouch(tmpArr[i], self); if(btEntityP(self)) btEntTouch(self, tmpArr[i]); } }
/** Calculate the physical center-point of an entity, * which is not necessarily at its origin. */ BTSV_API vec3 btCalcCenter(btEntity self) { vec3 org, mid; mid=v3scale(v3add(self->mins, self->maxs), 0.5); org=v3add(self->origin, mid); return(org); }
BTSV_API int btPointBoxContents(vec3 org, vec3 mins, vec3 maxs, btEntity forent) { vec3 am, an; am=v3add(org, mins); an=v3add(org, maxs); return(btBoxContents(am, an, forent)); }
void btEntityPlaneExtents(btEntity ent, vec4 norm, float *rm, float *rn) { float mins[3], maxs[3], nv[4]; vfvec3(mins, v3add(ent->origin, ent->mins)); vfvec3(maxs, v3add(ent->origin, ent->maxs)); vfvec4(nv, norm); Hull_BoxPlaneExtents(mins, maxs, nv, rm, rn); }
BTSV_API vec3 btBoxStepMove(vec3 org, vec3 mins, vec3 maxs, vec3 ivel, float dt, btEntity self) { vec3 org1; #if 1 if(self) { self->flags&=~(BT_FL_SIMPLEMOVE|BT_FL_OFFGROUND|BT_FL_JUMPMOVE); self->impulseVelocity=ivel; if(self->flags&BT_FL_CLIENT) { // self->flags&=~(BT_FL_ONGROUND); } } if(self && (self->flags&BT_FL_NOCLIP)) { org1=v3add(org, v3scale(ivel, dt)); return(org1); } #endif org1=btBoxStepMoveI(org, mins, maxs, ivel, dt, self); return(org1); }
BTEIFGL_API void BGBDT_Part_ParticleExplosionBasic( vec3d org, vec3 bvel, vec3 rvel, int cnt, int atxy, u32 clr) { BGBDT_Particle *tmp; vec3 tvel, trvel; int i; for(i=0; i<cnt; i++) { // trvel=vec3( // bgbdt_part_scurve(bgbdt_part_randsf()), // bgbdt_part_scurve(bgbdt_part_randsf()), // bgbdt_part_scurve(bgbdt_part_randsf())); // trvel=vec3( // bgbdt_part_scurve(bgbdt_part_randf())*2-1, // bgbdt_part_scurve(bgbdt_part_randf())*2-1, // bgbdt_part_scurve(bgbdt_part_randf())*2-1); trvel=vec3( bgbdt_part_randsf(), bgbdt_part_randsf(), bgbdt_part_randsf()); trvel=v3norm(trvel); trvel=v3scale(trvel, 1.0+bgbdt_part_randsf()*0.25); tvel=v3add(bvel, v3mul(rvel, trvel)); tmp=BGBDT_Part_SpawnParticle(org, tvel, atxy); tmp->clr=clr; tmp->ttl=500; } }
BTEIFGL_API void BGBDT_Part_ParticleEmitPara( BGBDT_ParticleEmission *para) { BGBDT_Particle *tmp; vec3 tvel, trvel; int i; for(i=0; i<para->cnt; i++) { trvel=vec3( bgbdt_part_randsf(), bgbdt_part_randsf(), bgbdt_part_randsf()); trvel=v3norm(trvel); trvel=v3scale(trvel, 1.0+bgbdt_part_randsf()*0.25); tvel=v3add(para->bvel, v3mul(para->rvel, trvel)); tmp=BGBDT_Part_SpawnParticle(para->org, tvel, para->atxy); tmp->zacc=para->zacc; tmp->clr=para->clr; tmp->clrvel=para->clrvel; tmp->rad=para->rad; tmp->ttl=para->ttl; BGBDT_Part_UpdateParticleClr(tmp, bgbdt_part_randsf()*0.2); } }
/** Calculate the bounding radius for an entity from its center. */ BTSV_API float btCalcRadius(btEntity self) { vec3 org; float rad; // org=btCalcCenter(self); org=v3scale(v3add(self->mins, self->maxs), 0.5); rad=v3len(v3sub(self->maxs, org)); return(rad); }
/** * Determine if origin and bbox represent a place an entity can stand. * Dist determines how far to look downwards for ground. * This version will check points, and is only true if all of the points * happen to align with the ground. */ BTSV_API int btCheckGroundDistPts(vec3 org, vec3 mins, vec3 maxs, float dist, btEntity forent) { BTGE_Trace tr; vec3 org1, org2; int i; if(!btCheckGroundDist(org, mins, maxs, dist, forent)) return(0); org1=v3add(org, vec3(0, 0, v3z(mins)-dist)); // i=btPointBoxContents(org1, mins, maxs, forent); // if(!i) i=btTraceline(&tr, org, org1, BT_TRACE_MONSTERS|BT_TRACE_BSPSOLID, forent); if(!i)return(0); // if(tr.fraction>=1.0)return(0); #if 0 org2=v3add(org1, vec3(v3x(mins), v3y(mins), 0)); i=btTraceline(&tr, org, org2, BT_TRACE_MONSTERS|BT_TRACE_BSPSOLID, forent); if(!i)return(0); org2=v3add(org1, vec3(v3x(maxs), v3y(mins), 0)); i=btTraceline(&tr, org, org2, BT_TRACE_MONSTERS|BT_TRACE_BSPSOLID, forent); if(!i)return(0); org2=v3add(org1, vec3(v3x(mins), v3y(maxs), 0)); i=btTraceline(&tr, org, org2, BT_TRACE_MONSTERS|BT_TRACE_BSPSOLID, forent); if(!i)return(0); org2=v3add(org1, vec3(v3x(maxs), v3y(maxs), 0)); i=btTraceline(&tr, org, org2, BT_TRACE_MONSTERS|BT_TRACE_BSPSOLID, forent); if(!i)return(0); #endif return(1); }
void go_to_waiting_point() { vec3d v; if (check_all_conflict(&loc,&waitingPoint,NULL)) { printf("GAHA:CONFLICT\n"); v3sub(&waitingPoint,&loc,&v); v3simpleRotateY(&v,45); v3add(&v,&loc,&v); go_to_destination(&v); } else { go_to_destination(&waitingPoint); } }
vec3 BTGE_EntBSP_CalcEntityListOrigin(btWorld wrl, btEntity lst) { btEntity cur; vec3 org; int i, n; cur=lst; org=vec3(0,0,0); n=0; while(cur) { org=v3add(org, btCalcCenter(cur)); n++; cur=cur->chain; } if(!n)n=1; org=v3scale(org, 1.0/n); return(org); }
vec4 BTGE_EntBSP_CalcEntityListNodePlane(btWorld wrl, btEntity lst, vec3 org) { btEntity cur; vec3 dir, tdir; vec4 norm; int i, n; cur=lst; dir=v3zero(); while(cur) { tdir=v3sub(btCalcCenter(cur), org); tdir=v3abs(tdir); dir=v3add(dir, tdir); cur=cur->chain; } dir=v3norm(dir); norm=v4plane(dir, v3dot(org, dir)); return(norm); }
BTSV_API void BT_BlockPlacerTouch(btEntity self, btEntity other) { BTGE_VoxelData *vox; btEntity nodmg; vec3 org; int x, y, z; int i; if(other) { if(other==self->owner)return; if(other->solidtype==BT_SOLID_NOT)return; if(other->solidtype==BT_SOLID_TRIGGER)return; i=btEntityBoxContents(other, self->absmin, self->absmax); if(!(i&BT_CONTENTS_CHECKSOLID))return; if(i&BT_CONTENTS_SKY)return; } nodmg=NULL; if(self->owner && (self->owner->flags&BT_FL_MONSTER)) { //monsters shouldn't blow themselves up with their own missiles nodmg=self->owner; } self->vt->touch=NULL; if(!nodmg)nodmg=other; if(self->state>=0) { // org=v3sub(self->origin, v3scale(self->velocity, 0.01)); org=self->origin; }else { org=v3add(self->origin, v3scale(self->velocity, 0.025)); } // x=v3x(org)/32; // y=v3y(org)/32; // z=v3z(org)/32; x=floor(v3x(org)/32); y=floor(v3y(org)/32); z=floor(v3z(org)/32); vox=BTGE_Voxel_GetWorldVoxel(btCurrentWorld(), x, y, z); if((self->state>0) && (!vox || !vox->type)) { //place block vox=BTGE_Voxel_GetWorldVoxelDirty(btCurrentWorld(), x, y, z); vox->type=self->state; btSound(self, BT_CHAN_VOICE, "sound/weapons/blkset0", 1.0, BT_ATTN_NORM); BT_EntitySmallSparksExplode(self); return; } if((self->state<0) && vox && (vox->type>0)) { //destroy block vox=BTGE_Voxel_GetWorldVoxelDirty(btCurrentWorld(), x, y, z); vox->type=0; btSound(self, BT_CHAN_VOICE, "sound/weapons/blkbrk0", 1.0, BT_ATTN_NORM); BT_EntitySmallSparksExplode(self); return; } if(self->state<0) { BT_RadiusDamage(self, self->owner, self->damage, nodmg, self->height, BT_MOD_BLASTER); btSound(self, BT_CHAN_VOICE, "sound/weapons/blkbrk0", 1.0, BT_ATTN_NORM); BT_EntitySmallSparksExplode(self); return; } // BT_Damage(other, self->owner, self->damage, BT_MOD_BLASTER); // BT_RadiusDamage(self, self->owner, self->damage, nodmg, // self->height, BT_MOD_BLASTER); // BT_EntitySparksExplode(self); }
void BT_MonsterStartGo(btEntity self) { btEntity cur, lst; // if(!self->eAct)self->eAct=gcalloc(sizeof(BTGE_EntityActor)); if(!btWalkmove(self, 0, 0)) self->origin=v3add(self->origin, vec3(0, 0, 8)); if(!btWalkmove(self, 0, 0)) { //started in solid btDPrint("monster %s start solid at (%s)\n", self->classname, btVec3ToStr(self->origin)); } if(self->health==0) self->health=25; if(self->maxHealth==0) self->maxHealth=self->health; if(!self->ttsVoice) self->ttsVoice="female0"; self->takedamage=BT_DAMAGE_AIM; self->idealYaw=btCurrentYaw(self); if(self->yawSpeed==0) self->yawSpeed=360; self->vieworg=vec3(0,0,25); self->f_use=BT_MonsterUse; self->flags|=BT_FL_MONSTER; if(self->target) { lst=btFindTargets(self->target); if(!lst) { btDPrint("monster %s missing target at (%s)\n", self->classname, btVec3ToStr(self->origin)); } cur=lst; while(cur) { if(!strcmp(cur->classname, "path_corner")) self->goalEntity=cur; if(!strcmp(cur->classname, "path_corner_event")) self->goalEntity=cur; cur=cur->chain; } } if(self->goalEntity) { self->moveTarget=self->goalEntity; BTAI_ScriptedSetNode(self, self->goalEntity); if(self->anim) return; #if 0 self->moveTarget=self->goalEntity; if(self->goalEntity==self) { self->goalEntity=NULL; self->moveTarget=self->goalEntity; } #endif } if(self->moveTarget) { btEntWalk(self); }else { self->pauseTime=btDelayTime(999999); btEntStand(self); } BT_EntityDialogSetupTest(self); }
BTSV_API int btWalkmove(btEntity self, float yaw, float dist) { vec3 org, dir, org1; int i; if(dist>0) { // printf("btWalkmove: %d %f, %d %d\n", (int)yaw, dist, // (int)self->idealYaw, (int)btCurrentYaw(self)); } #if 1 if(self->flags&BT_FL_SCRIPTED) { //predict and update flags as usual // dir=BT_TargetDirection(self, self->goalEntity); // dir=v3scale(dir, dist/btge_framedt); dir=v3scale(btYawVector(yaw), dist/btge_framedt); org=btBoxStepMove(self->origin, self->mins, self->maxs, dir, btge_framedt, self); if(self->flags&BT_FL_SIMPLEMOVE) { self->origin=org; return(1); } //but force the movement org=v3add(self->origin, v3scale(dir, btge_framedt)); self->origin=org; return(1); } #endif #if 1 // btge_tempSelf=self; dir=v3scale(btYawVector(yaw), dist/btge_framedt); org=btBoxStepMove(self->origin, self->mins, self->maxs, dir, btge_framedt, self); self->origin=org; // btge_tempSelf=NULL; if(self->flags&BT_FL_SIMPLEMOVE) return(1); return(0); #endif #if 0 //calculate desired spot dir=v3scale(btYawVector(yaw), dist); org=v3add(self->origin, dir); if(self->flags&BT_FL_FLY) { if(btCheckFlySpot(org, self->mins, self->maxs, self)) { self->origin=org; return(1); } return(0); } if(self->flags&BT_FL_SWIM) { if(btCheckSwimSpot(org, self->mins, self->maxs, self)) { self->origin=org; return(1); } return(0); } if(btCheckOnGround(org, self->mins, self->maxs, self)) { //ok, no problem self->origin=org; return(1); } if(btCheckGroundDist(org, self->mins, self->maxs, 12, self)) { //ok, but no longer on-ground (gone off a step or similar) BT_WalkmovePointAdjGround(self, org); // self->flags&=~BT_FL_ONGROUND; // self->origin=org; return(1); } org1=v3add(org, vec3(0,0,8)); if(btCheckGroundDist(org1, self->mins, self->maxs, 12, self)) { //ok, but went up a step or similar BT_WalkmovePointAdjGround(self, org1); return(1); } //can't go there return(0); #endif }
vec3 btBoxStepMoveI(vec3 org, vec3 mins, vec3 maxs, vec3 ivel, float dt, btEntity self) { vec3 norg, org1, org2, org3; float f; int i, j; if(dt>0.5) { return(org); } if(dt>(1.0/24)) { f=dt*0.5; org1=btBoxStepMoveI(org, mins, maxs, ivel, f, self); if(self && (self->flags&BT_FL_JUMPMOVE)) return(btBoxStepMoveFall(org1, mins, maxs, f, self)); org2=btBoxStepMoveI(org1, mins, maxs, ivel, f, self); return(org2); } #if 0 if(self) { self->flags&=~(BT_FL_SIMPLEMOVE|BT_FL_OFFGROUND|BT_FL_JUMPMOVE); self->impulseVelocity=ivel; if(self->flags&BT_FL_CLIENT) { // self->flags&=~(BT_FL_ONGROUND); } } if(self && (self->flags&BT_FL_NOCLIP)) { org1=v3add(org, v3scale(ivel, dt)); return(org1); } #endif //can't move if dead if(self && (self->health<0)) { org1=btBoxStepMoveFall(org, mins, maxs, dt, self); return(org1); } org1=v3add(org, v3scale(ivel, dt)); // f=64*dt; // org2=v3sub(org1, vec3(0, 0, f)); i=btPointBoxContents(org1, mins, maxs, self); // j=btPointBoxContents(org2, mins, maxs); // if(!i) if(!(i&BT_CONTENTS_PLAYERSOLID)) { if(self)self->flags|=BT_FL_SIMPLEMOVE; org2=btBoxStepMoveFall(org1, mins, maxs, dt, self); #if 0 if(self && (self->flags&BT_FL_MONSTER) && !(self->flags&(BT_FL_ONGROUND|BT_FL_FLY|BT_FL_SWIM))) { //ok, not onground, assume walked off a ledge self->flags&=~BT_FL_SIMPLEMOVE; org2=btBoxStepMoveFall(org, mins, maxs, dt, self); } #endif #if 1 if(self && (self->flags&BT_FL_MONSTER) && !(self->flags&(BT_FL_FLY|BT_FL_SWIM))) { // j=btCheckGroundDist(org1, mins, maxs, 16, self); // j=btCheckGroundDist(org1, mins, maxs, 24, self); // j=btCheckGroundDistPts(org1, mins, maxs, 24, self); j=btCheckGroundDistPts(org1, mins, maxs, 36, self); if(!j) { printf("btBoxStepMove: %d Ledge Detect Handle\n", self->entnum); self->flags&=~BT_FL_SIMPLEMOVE; org2=btBoxStepMoveFall(org, mins, maxs, dt, self); } } #endif return(org2); } if((fabs(v3x(ivel))>fabs(v3z(ivel))) && (fabs(v3y(ivel))>fabs(v3z(ivel)))) { //assume sliding along ground org1=vec3(v3x(org1), v3y(org1), v3z(org)); i=btPointBoxContents(org1, mins, maxs, self); // if(!i)return(org1); if(!(i&BT_CONTENTS_PLAYERSOLID)) { if(self)self->flags|=BT_FL_SIMPLEMOVE; return(btBoxStepMoveFall(org1, mins, maxs, dt, self)); // return(org1); } } for(j=0; j<4; j++) { org2=vec3(v3x(org1), v3y(org1), v3z(org1)+(j+1)*4); i=btPointBoxContents(org2, mins, maxs, self); // if(!i)return(org2); if(!(i&BT_CONTENTS_PLAYERSOLID)) { if(self)self->flags|=BT_FL_SIMPLEMOVE; return(btBoxStepMoveFall(org2, mins, maxs, dt, self)); // return(org2); } } if(self && (self->flags&BT_FL_MONSTER)) { org2=vec3(v3x(org1), v3y(org1), v3z(org1)+34); i=btPointBoxContents(org2, mins, maxs, self); // if(!i)return(org2); if(!(i&BT_CONTENTS_PLAYERSOLID)) { printf("btBoxStepMove: %d Jump Move, flags=%08X\n", self->entnum, self->flags); self->flags|=BT_FL_JUMPMOVE; return(btBoxStepMoveFall(org, mins, maxs, dt, self)); } } #if 0 if(self && (self->flags&BT_FL_MONSTER) && !(self->flags&(BT_FL_FLY|BT_FL_SWIM))) { // printf("btBoxStepMove: %d Compound Move\n", // self->entnum); return(btBoxStepMoveFall(org, mins, maxs, dt, self)); } #endif org2=btBoxStepMoveSlide(org, mins, maxs, ivel, dt, org1, self); i=btPointBoxContents(org2, mins, maxs, self); // if(!i)return(org2); if(!(i&BT_CONTENTS_PLAYERSOLID)) { if(self)self->flags|=BT_FL_SIMPLEMOVE; return(btBoxStepMoveFall(org2, mins, maxs, dt, self)); } for(j=0; j<4; j++) { org2=vec3(v3x(org1), v3y(org1), v3z(org1)+(j+1)*4); // i=btPointBoxContents(org2, mins, maxs); // if(!i)return(org2); org2=btBoxStepMoveSlide(org, mins, maxs, ivel, dt, org2, self); i=btPointBoxContents(org2, mins, maxs, self); if(!(i&BT_CONTENTS_PLAYERSOLID)) { if(self)self->flags|=BT_FL_SIMPLEMOVE; return(btBoxStepMoveFall(org2, mins, maxs, dt, self)); } } return(btBoxStepMoveFall(org, mins, maxs, dt, self)); // return(org); }
BTSV_API vec3 btBoxStepMoveFall( vec3 org, vec3 mins, vec3 maxs, float dt, btEntity self) { vec3 org1, org2, vel; float f; int i, j; f=256*dt; vel=vec3(0, 0, -f); if(self) { // self->flags&=~BT_FL_INWATER; self->flags&=~(BT_FL_ONGROUND|BT_FL_INWATER); //flying entities don't fall if(self->flags&BT_FL_FLY) return(org); vel=v3scale(self->velocity, dt); } // f=64*dt; // f=256*dt; // org1=v3sub(org, vec3(0, 0, f)); org1=v3add(org, vel); i=btPointBoxContents(org1, mins, maxs, self); if(i&BT_CONTENTS_PLAYERSOLID) { if(self) { if(self->flags&BT_FL_CLIENT) { // printf("client impact\n"); // BT_ClientImpact(self, self->velocity); BT_ClientImpact(self, v3add(self->velocity, self->impulseVelocity)); } self->flags|=BT_FL_ONGROUND; self->velocity=vec3(0,0,0); j=btPointContents(org, self); if(j&BT_CONTENTS_FLUID) { self->flags|=BT_FL_INWATER; } } return(org); } if(self && (self->flags&BT_FL_CLIENT)) { org2=v3sub(org, vec3(0, 0, 2)); i=btPointBoxContents(org2, mins, maxs, self); if(i&BT_CONTENTS_PLAYERSOLID) { self->flags|=BT_FL_ONGROUND; } } j=btPointContents(org, self); if(j&BT_CONTENTS_FLUID) { if(self) { self->flags|=BT_FL_INWATER; //swim entities don't sink if(self->flags&BT_FL_SWIM) return(org); f=1.0-dt; if(f<0)f=0; self->velocity=v3scale(self->velocity, f); // self->velocity=vec3(0,0,0); } //reduced falling speed // f=16*dt; // org1=v3sub(org, vec3(0, 0, f)); if(!self) org1=v3addscale(org, vel, 0.25); } return(org1); }
void BT_WalkmonsterStartGo(btEntity self) { self->origin=v3add(self->origin, vec3(0, 0, 1)); btDropToFloor(self); BT_MonsterStartGo(self); }