bool AiEntity::useWeapon() { double time = mGameModel->physics->getLastUpdateTime(); if (mInventory[0] == 0) return false; if (mNextShotTime > time) return false; item_t item = mGameModel->itemManager->getItem(mInventory[0]); if (item.type != ITEMTYPE_GUN_ONE_HANDED) { return false; } v3d_t targetPosition = mTargetPhysicsEntity->boundingBox.getCenterPosition(); v3d_t vecToTarget = v3d_sub(targetPosition, mWorldPosition); double distanceToTarget = v3d_mag(vecToTarget); if (!isTargetInRange(item.gunType, distanceToTarget)) { return false; } shot_info_t shotInfo; shotInfo.angle = v3d_normalize(vecToTarget); shotInfo.ownerPhysicsHandle = mPhysicsHandle; shotInfo.position = mWorldPosition; shotInfo.time = time; mNextShotTime = mGameModel->itemManager->useGun(mInventory[0], shotInfo); return true; }
static void draw_bond_for_stick(int i,int j,GLdouble g, GabEditBondType bondType) { int k; V4d Specular1 = {1.0f,1.0f,1.0f,1.0f}; V4d Diffuse1 = {0.0f,0.0f,0.0f,1.0f}; V4d Ambiant1 = {0.0f,0.0f,0.0f,1.0f}; V4d Specular2 = {1.0f,1.0f,1.0f,1.0f}; V4d Diffuse2 = {0.0f,0.0f,0.0f,1.0f}; V4d Ambiant2 = {0.0f,0.0f,0.0f,1.0f}; GLdouble p1; GLdouble p2; GLdouble aspect = g; Specular1[0] = GeomOrb[i].Prop.color.red/(gdouble)65535; Specular1[1] = GeomOrb[i].Prop.color.green/(gdouble)65535; Specular1[2] = GeomOrb[i].Prop.color.blue/(gdouble)65535; Specular2[0] = GeomOrb[j].Prop.color.red/(gdouble)65535; Specular2[1] = GeomOrb[j].Prop.color.green/(gdouble)65535; Specular2[2] = GeomOrb[j].Prop.color.blue/(gdouble)65535; for(k=0;k<3;k++) { Diffuse1[k] = Specular1[k]*0.8; Diffuse2[k] = Specular2[k]*0.8; } for(k=0;k<3;k++) { Ambiant1[k] = Specular1[k]*0.5; Ambiant2[k] = Specular2[k]*0.5; } for(k=0;k<3;k++) { Ambiant1[k] = 0; Ambiant2[k] = 0; } for(k=0;k<3;k++) { Specular1[k] = 0.8; Specular2[k] = 0.8; } p1 = GeomOrb[i].Prop.covalentRadii+GeomOrb[i].Prop.radii; p2 = GeomOrb[j].Prop.covalentRadii+GeomOrb[j].Prop.radii; Cylinder_Draw_Color_Two(g,GeomOrb[i].C,GeomOrb[j].C, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); if( bondType == GABEDIT_BONDTYPE_SINGLE || ( !ShowMultiBondsOrb && (bondType == GABEDIT_BONDTYPE_DOUBLE || bondType == GABEDIT_BONDTYPE_TRIPLE) ) ) Cylinder_Draw_Color_Two(g,GeomOrb[i].C,GeomOrb[j].C, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); else if(bondType == GABEDIT_BONDTYPE_DOUBLE && ShowMultiBondsOrb) { V3d vScal = {g/aspect*0.35,g/aspect*0.35,g/aspect*0.35}; V3d C1; V3d C2; V3d cross; V3d sub; V3d CRing; getCentreRing(i,j, CRing); v3d_sub(CRing, GeomOrb[i].C, C1); v3d_sub(CRing, GeomOrb[j].C, C2); v3d_cross(C1, C2, cross); v3d_sub(GeomOrb[i].C, GeomOrb[j].C, sub); v3d_cross(cross, sub, vScal); if(v3d_dot(vScal,vScal)!=0) { v3d_normal(vScal); v3d_scale(vScal, g/aspect*0.35); } else getvScaleBond(g/aspect*0.35*2, C1,C2, vScal); for(k=0;k<3;k++) C1[k] = GeomOrb[i].C[k]; for(k=0;k<3;k++) C2[k] = GeomOrb[j].C[k]; Cylinder_Draw_Color_Two(g,C1,C2, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); for(k=0;k<3;k++) C1[k] = GeomOrb[i].C[k]-vScal[k]; for(k=0;k<3;k++) C2[k] = GeomOrb[j].C[k]-vScal[k]; Cylinder_Draw_Color_Two(g/2,C1,C2, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); } else if(bondType == GABEDIT_BONDTYPE_TRIPLE && ShowMultiBondsOrb) { V3d vScal = {g/aspect*0.35,g/aspect*0.35,g/aspect*0.35}; V3d C1; V3d C2; V3d cross; V3d sub; V3d CRing; getCentreRing(i,j, CRing); v3d_sub(CRing, GeomOrb[i].C, C1); v3d_sub(CRing, GeomOrb[j].C, C2); v3d_cross(C1, C2, cross); v3d_sub(GeomOrb[i].C, GeomOrb[j].C, sub); v3d_cross(cross, sub, vScal); if(v3d_dot(vScal,vScal)!=0) { v3d_normal(vScal); v3d_scale(vScal, g/aspect*0.35); } else getvScaleBond(g/aspect*0.35*2, C1,C2, vScal); for(k=0;k<3;k++) C1[k] = GeomOrb[i].C[k]-vScal[k]; for(k=0;k<3;k++) C2[k] = GeomOrb[j].C[k]-vScal[k]; Cylinder_Draw_Color_Two(g/2,C1,C2, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); for(k=0;k<3;k++) C1[k] = GeomOrb[i].C[k]; for(k=0;k<3;k++) C2[k] = GeomOrb[j].C[k]; Cylinder_Draw_Color_Two(g,C1,C2, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); for(k=0;k<3;k++) C1[k] = GeomOrb[i].C[k]+vScal[k]; for(k=0;k<3;k++) C2[k] = GeomOrb[j].C[k]+vScal[k]; Cylinder_Draw_Color_Two(g/2,C1,C2, Specular1,Diffuse1,Ambiant1, Specular2,Diffuse2,Ambiant2, p1,p2); } }
void AiEntity::updateHopper() { v3d_t movementForce = v3d_zero(); Physics& physics = *mGameModel->physics; double time = physics.getLastUpdateTime(); if (mPhysicsEntity->health < 0.0) { return; } if (r_numi(0, 1085) == 3) { physics.addSoundEvent(SOUND_TIGER_ROAR, mPhysicsEntity->pos); } // keep it afloat in water even without a target if (mTargetPhysicsHandle == 0 && mPhysicsEntity->worldViscosity > 0.0) { physics.add_force(mPhysicsHandle, v3d_v(0.0, 4200.0, 0.0)); } else if (physics.getIndexFromHandle(mTargetPhysicsHandle) >= 0) { PhysicsEntity *targetPhysicsEntity = physics.getEntityByHandle(mTargetPhysicsHandle); v3d_t targetPosition = targetPhysicsEntity->boundingBox.getCenterPosition(); v3d_t vecToTarget = v3d_sub(targetPosition, mWorldPosition); if (mPhysicsEntity->worldViscosity > 0.0) { if (v3d_mag(vecToTarget) < mMinDistanceToPlayer) { vecToTarget = v3d_scale(1600.0 * (sin(time * 8.0) + 1.5), v3d_normalize(vecToTarget)); movementForce = v3d_add(movementForce, vecToTarget); // give it a little more buoyancy if (targetPosition.y - mWorldPosition.y > 0.0) { physics.add_force(mPhysicsHandle, v3d_v(0.0, 2000.0, 0.0)); } } } else if (mPhysicsEntity->on_ground) { vecToTarget.y = 0.0; if (v3d_mag(vecToTarget) < mMinDistanceToPlayer) { // big leap? if (r_numi(0, 60) == 3) { vecToTarget = v3d_scale(15000.0, v3d_normalize(vecToTarget)); vecToTarget.y = 60000.0; movementForce = v3d_add(movementForce, vecToTarget); } else { vecToTarget = v3d_scale(2000.0, v3d_normalize(vecToTarget)); //vecToTarget.y = r_num(8000.0, 10000.0); movementForce = v3d_add(movementForce, vecToTarget); } } } else { vecToTarget.y = 0.0; if (v3d_mag(vecToTarget) < mMinDistanceToPlayer) { vecToTarget = v3d_scale(5.0, v3d_normalize(vecToTarget)); // vecToPlayer.y = 20.0; movementForce = v3d_add(movementForce, vecToTarget); } } physics.add_force(mPhysicsHandle, movementForce); } }
void AiEntity::updateBalloon() { v3d_t movementForce = v3d_zero(); Physics& physics = *mGameModel->physics; double time = physics.getLastUpdateTime(); if (mPhysicsEntity->worldViscosity > 0.0) { physics.add_force(mPhysicsHandle, v3d_v(0.0, 120.0, 0.0)); } if (physics.getIndexFromHandle(mTargetPhysicsHandle) >= 0) { // we can't fly if we're on the ground! if (mPhysicsEntity->on_ground) { // movementForce = v3d_v(0.0, 8000.0, 0.0); physics.add_force(mPhysicsHandle, v3d_v(0.0, 8000.0, 0.0)); } PhysicsEntity* targetPhysicsEntity = physics.getEntityByHandle(mTargetPhysicsHandle); if (targetPhysicsEntity == NULL) { printf("AiEntity::updateBalloon() - target is NULL\n"); return; } v3d_t targetPosition = targetPhysicsEntity->boundingBox.getCenterPosition(); // let's keep this thing afloat double desiredHeight; if (targetPhysicsEntity->aiType == AITYPE_HOPPER || targetPhysicsEntity->aiType == AITYPE_SHOOTER || targetPhysicsEntity->aiType == AITYPE_PLAYER) { double sin2 = (2.0 * sin(time)); desiredHeight = targetPosition.y + 14.0 + sin2; double height2 = mGameModel->location->getWorldMap()->mPeriodics->getTerrainHeight(mWorldPosition.x, mWorldPosition.z) + 10.0 + sin2; if (height2 > desiredHeight) { desiredHeight = height2; } } else { // this is so that when floaters fight they don't just keep flying higher desiredHeight = mGameModel->location->getWorldMap()->mPeriodics->getTerrainHeight(mWorldPosition.x, mWorldPosition.z) + 10.0 + (2.0 * sin(time)); } double delta = mWorldPosition.y - desiredHeight; if (delta > 0.0) { // delta += 0.2 * mPhysicsEntity.vel.y; delta = 0.0; } else if (delta < 0.0) { delta += 0.2 * mPhysicsEntity->vel.y; } double forceMagnitude = 5.0 * (delta * delta); //; - physicsEntity.vel.y; if (forceMagnitude > 200.0) { forceMagnitude = 200.0; } if (delta > 0.0) { movementForce = v3d_v(0.0, -0.5 * forceMagnitude, 0.0); } else { movementForce = v3d_v(0.0, forceMagnitude, 0.0); } // try to get to the target v3d_t vecToTarget = v3d_sub(targetPosition, mWorldPosition); vecToTarget.y = 0.0; v3d_t velNoY = mPhysicsEntity->vel; velNoY.y = 0.0; // FIXME: there needs to be a check here to see if the AI // is going the 'long way' to turn towards it's target double angle1 = atan2(vecToTarget.x, vecToTarget.z); double angle2 = atan2(velNoY.x, velNoY.z); double angle = angle1 - angle2; if (abs(angle) > 0.1) { if (abs(angle) > M_PI) { angle = -angle; } angle = absConstrain(angle, 0.01); v3d_t rot = v3d_rotateY(mPhysicsEntity->vel, angle); mPhysicsEntity->vel.x = rot.x; mPhysicsEntity->vel.z = rot.z; } if (v3d_mag(vecToTarget) < mMinDistanceToPlayer) { vecToTarget = v3d_scale(15.0, v3d_normalize(vecToTarget)); movementForce = v3d_add(movementForce, vecToTarget); } // physics.add_force (mPhysicsHandle, movementForce); // mPhysicsEntity->force = v3d_add(mPhysicsEntity->force, movementForce); mPhysicsEntity->force.x += movementForce.x; mPhysicsEntity->force.y += movementForce.y; mPhysicsEntity->force.z += movementForce.z; } }
bool WorldMap::lineOfSight(const v3d_t &a, const v3d_t &b) const { v3d_t diff = v3d_sub(b, a); int start; int end; int add; // x-axis if (diff.x != 0.0) { // && (floor (a.x) != floor (b.x))) { int direction = static_cast<int>(sign (diff.x)); if (direction > 0) { start = static_cast<int>(ceil (a.x)); end = static_cast<int>(floor (b.x)); add = 1; } else { start = static_cast<int>(floor (a.x)); end = static_cast<int>(ceil (b.x)); add = -1; } for (int x = start; x != (end + add); x += add) { double percent = (static_cast<double>(x) - static_cast<double>(a.x)) / (static_cast<double>(b.x) - static_cast<double>(a.x)); v3d_t pos = v3d_interpolate(a, b, percent); v3di_t blockPos; if (add > 0) { blockPos.x = x; } else { blockPos.x = x + add; } blockPos.y = static_cast<int>(floor(pos.y)); blockPos.z = static_cast<int>(floor(pos.z)); if (isSolidBlock(blockPos)) { return false; } } } // y-axis if (diff.y != 0.0) { // && (floor (a.y) != floor (b.y))) { int direction = static_cast<int>(sign (diff.y)); if (direction > 0) { start = static_cast<int>(ceil (a.y)); end = static_cast<int>(floor (b.y)); add = 1; } else { start = static_cast<int>(floor (a.y)); end = static_cast<int>(ceil (b.y)); add = -1; } for (int y = start; y != (end + add); y += add) { double percent = (static_cast<double>(y) - static_cast<double>(a.y)) / (static_cast<double>(b.y) - static_cast<double>(a.y)); v3d_t pos = v3d_interpolate (a, b, percent); v3di_t blockPos; blockPos.x = static_cast<int>(floor (pos.x)); if (add > 0) { blockPos.y = y; } else { blockPos.y = y + add; } blockPos.z = static_cast<int>(floor (pos.z)); if (isSolidBlock (blockPos)) { return false; } } } // z-axis if (diff.z != 0.0) { // && (floor (a.z) != floor (b.z))) { int direction = static_cast<int>(sign (diff.z)); if (direction > 0) { start = static_cast<int>(ceil (a.z)); end = static_cast<int>(floor (b.z)); add = 1; } else { start = static_cast<int>(floor (a.z)); end = static_cast<int>(ceil (b.z)); add = -1; } for (int z = start; z != (end + add); z += add) { double percent = (static_cast<double>(z) - static_cast<double>(a.z)) / (static_cast<double>(b.z) - static_cast<double>(a.z)); v3d_t pos = v3d_interpolate (a, b, percent); v3di_t blockPos; blockPos.x = static_cast<int>(floor (pos.x)); blockPos.y = static_cast<int>(floor (pos.y)); if (add > 0) { blockPos.z = z; } else { blockPos.z = z + add; } if (isSolidBlock (blockPos)) { return false; } } } return true; }
bool WorldMap::rayCastSolidBlock(const v3d_t &a, const v3d_t &b, v3di_t &hitPosition, int &face) const { v3d_t diff = v3d_sub(b, a); double magnitude = v3d_mag(diff); double step = 1.0 / (10.0 * magnitude); v3di_t blockPosition; v3d_t pos; v3d_t lastPos = a; static v3d_t faceAdd[6] = { {{ 0.0, 0.0, 0.0 }}, // BLOCK_SIDE_LEF {{ 1.0, 0.0, 0.0 }}, // BLOCK_SIDE_RIG {{ 0.0, 1.0, 0.0 }}, // BLOCK_SIDE_TOP {{ 0.0, 0.0, 0.0 }}, // BLOCK_SIDE_BOT {{ 0.0, 0.0, 1.0 }}, // BLOCK_SIDE_FRO {{ 0.0, 0.0, 0.0 }} // BLOCK_SIDE_BAC }; for (double t = step; t <= 1.0; t += step) { pos = v3d_add (a, v3d_scale (t, diff)); // TODO: check if this is the same v3di_t that was checked last frame blockPosition = v3di_v (pos); block_t *block = getBlock(blockPosition); // special case for plants... if (block != NULL && gBlockData.get(block->type)->solidityType == BLOCK_SOLIDITY_TYPE_PLANT) { hitPosition = blockPosition; face = 0; return true; } if (isSolidBlock(blockPosition)) { // the return value gets set hitPosition = blockPosition; // figure out which face was intersected first double faceHitResults[NUM_BLOCK_SIDES]; double faceHitTimes[NUM_BLOCK_SIDES]; for (int s = 0; s < NUM_BLOCK_SIDES; s++) { Plane3d plane; v3d_t point = v3d_add(v3d_v(blockPosition), faceAdd[s]); v3d_t normal = { gCubeFaceNormalLookup[s][0], gCubeFaceNormalLookup[s][1], gCubeFaceNormalLookup[s][2] }; plane.setFromPointAndNormal(point, normal); faceHitResults[s] = plane.doesLineSegmentIntersect(lastPos, pos, faceHitTimes[s]); } double soonestHit = 1000.0; // super high value // this section sets the 'face' variable to the nearest face for (int s = 0; s < NUM_BLOCK_SIDES; s++) { if (faceHitResults[s]) { if (faceHitTimes[s] > 0.0 && faceHitTimes[s] < soonestHit) { soonestHit = faceHitTimes[s]; face = s; } } } return true; } lastPos = pos; } return false; }