Example #1
0
lod *lodLevelGet(void *spaceObj, vector *camera, vector *ship)
{
    real32 distance;
    SpaceObj *obj = (SpaceObj *)spaceObj;
    lodinfo *info = obj->staticinfo->staticheader.LOD;

    dbgAssert(info != NULL);                                //verify the LOD table exists

    vecSub(obj->cameraDistanceVector,*camera,*ship);
    obj->cameraDistanceSquared = distance = vecMagnitudeSquared(obj->cameraDistanceVector);

#if LOD_SCALE_DEBUG
    if (lodDebugScaleFactor != 0.0f)
    {
        lodScaleFactor = lodDebugScaleFactor;
    }
#endif
    if (distance > info->level[obj->currentLOD].bOff * lodScaleFactor)
    {                                                       //if drop a level of detail
        do
        {
            obj->currentLOD++;                                  //go to lower level
            if (obj->currentLOD >= info->nLevels)
            {
                obj->currentLOD = info->nLevels-1;
                break;
            }
        }
        while (distance > info->level[obj->currentLOD].bOff * lodScaleFactor);
    }
    else
    {
        while (obj->currentLOD > 0 && distance < info->level[obj->currentLOD - 1].bOn * lodScaleFactor)
        {                                                   //if go higher level of detail
            obj->currentLOD--;                              //go to higher level
        }
    }
    dbgAssert(obj->currentLOD >= 0);
    dbgAssert(obj->currentLOD < info->nLevels);             //verify we are within the available levels of detail
#if LOD_PRINT_DISTANCE
    if (keyIsStuck(WKEY))
    {
        keyClearSticky(WKEY);
        lodScaleFactor *= 0.99f;
        dbgMessagef("\nlodScaleFactor = %.3f", lodScaleFactor);
    }
    if (keyIsStuck(OKEY))
    {
        keyClearSticky(OKEY);
        lodScaleFactor *= 1.01f;
        dbgMessagef("\nlodScaleFactor = %.3f", lodScaleFactor);
    }
    if (lodTuningMode)
    {
        obj->currentLOD = min(rndLOD, info->nLevels - 1);
        return(&info->level[min(rndLOD, info->nLevels - 1)]);
    }
#endif
    return(&info->level[obj->currentLOD]);                  //return pointer to lod structure
}
Example #2
0
void getRotatePoint(Ship *ship, vector *point, real32 *distance)
{
    Node *slavenode;
    Ship *slave;
    udword count;
    vector dist;

    dbgAssertOrIgnore(ship->flags & SOF_Slaveable);     //ship should be slaveable
    dbgAssertOrIgnore(ship->slaveinfo->slaves.num >= 5);    //need enough for a pie plate!

    slavenode = ship->slaveinfo->slaves.head;
    point->x = ship->posinfo.position.x;
    point->y = ship->posinfo.position.y;
    point->z = ship->posinfo.position.z;

    count = 0;
    while (count < 5)
    {
        slave = (Ship *) listGetStructOfNode(slavenode);
        vecAdd(*point, *point, slave->posinfo.position);
        slavenode = slavenode->next;
        count++;
    }
    point->x /= 6.0f;
    point->y /= 6.0f;
    point->z /= 6.0f;

    vecSub(dist,ship->posinfo.position, *point);
    *distance = vecMagnitudeSquared(dist);
    *distance = fsqrt(*distance);
}
Example #3
0
void vecNormalize(LWONormal *a)
{
    float mag = (float)sqrt(vecMagnitudeSquared(*a));

    a->x /= mag;
    a->y /= mag;
    a->z /= mag;
}
Example #4
0
/*-----------------------------------------------------------------------------
    Name        : vecCopyAndNormalize
    Description : copies a source vector to destination vector, and then
                  normalizes the destination vector
    Inputs      : src, dst
    Outputs     :
    Return      :
----------------------------------------------------------------------------*/
void vecCopyAndNormalize(vector *src,vector *dst)
{
    real32 mag = fsqrt(vecMagnitudeSquared(*src));
    real32 oneOverMag = 1.0f / mag;

    dst->x = src->x * oneOverMag;
    dst->y = src->y * oneOverMag;
    dst->z = src->z * oneOverMag;
}
Example #5
0
/*-----------------------------------------------------------------------------
    Name        : vecNormalize
    Description : normalizes a vector (makes it a unit vector)
    Inputs      : vector
    Outputs     : vector is normalized
    Return      :
----------------------------------------------------------------------------*/
void vecNormalize(vector *a)
{
    real32 mag = fsqrt(vecMagnitudeSquared(*a));
    real32 oneOverMag = 1.0f / mag;

    a->x *= oneOverMag;
    a->y *= oneOverMag;
    a->z *= oneOverMag;
}
Example #6
0
void P2MultiBeamFrigateAttackDoAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist,bool PassiveAttack)

{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;

    P2MultiBeamFrigateStatics *frigstat = (P2MultiBeamFrigateStatics *)shipstaticinfo->custstatinfo;
    P2MultiBeamFrigateSpec    *spec     = (P2MultiBeamFrigateSpec *)ship->ShipSpecifics;

    vector trajectory;
    vector shipRightVec;
    real32 range;

        spec->aiattacklast = universe.totaltimeelapsed;
    ship->autostabilizeship = FALSE;

    aishipGetTrajectory(ship, target, &trajectory);
    range = RangeToTarget(ship,target,&trajectory);

    if (range > frigstat->MultiBeamRange[ship->tacticstype])
    {
        //not in range
        if(!PassiveAttack)
        {
            //do aiship fly to stuff here

            //if not in range...fly to the ship
            //else track zero velocity
                aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
        }
        return;
    }

    //we are in range

    vecNormalize(&trajectory);
    if(!PassiveAttack)
	{
		aitrackZeroVelocity(ship);
	}
    matGetVectFromMatrixCol2(shipRightVec,ship->rotinfo.coordsys);

    aitrackHeadingAndUp(ship,&trajectory,&shipRightVec,0.9999f);

    
	if(vecMagnitudeSquared(ship->rotinfo.rotspeed) > frigstat->AttackRotationSpeed)
    {
		if(aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC|AITRACK_DONT_ZERO_ME))
		{
			//rotation speed reached
			//lets fire guns if we can
			P2MultiBeamFrigateFire(ship,target);
		}
    }
}
Example #7
0
/*-----------------------------------------------------------------------------
    Name        : vecCapMinVector
    Description : limits a vector's minimum magnitude from growing below a maximum
                  magnitude
    Inputs      : vectorToCap, minMagnitude
    Outputs     :
    Return      :
----------------------------------------------------------------------------*/
void vecCapMinVector(vector *vectorToCap,real32 minMagnitude)
{
    real32 actualMag = fsqrt(vecMagnitudeSquared(*vectorToCap));
    real32 ratio;

    if (actualMag < minMagnitude)
    {
        ratio = minMagnitude / actualMag;
        vectorToCap->x *= ratio;
        vectorToCap->y *= ratio;
        vectorToCap->z *= ratio;
    }
}
Example #8
0
//fires the bursts for the ship
bool doBurstFire(Ship *ship)
{
    HeavyCorvetteSpec *spec = (HeavyCorvetteSpec *)ship->ShipSpecifics;
    GunInfo *gunInfo = ship->gunInfo;
    sdword numGuns = gunInfo->numGuns;
    //Gun *gun;
    sdword done;
    vector trajectory,heading;
    real32 range,one_over_range;
    SpaceObjRotImpTarg dummyTarg;

    vecSub(trajectory,spec->burstFireVector,ship->posinfo.position);
    range = vecMagnitudeSquared(trajectory);
    range = fsqrt(range);
    one_over_range = 1.0f/range;
    vecScalarMultiply(trajectory,trajectory,one_over_range);

    dummyTarg.objtype = OBJ_ShipType;
    dummyTarg.posinfo.position = spec->burstFireVector;
    dummyTarg.collInfo.collPosition = spec->burstFireVector;
    dummyTarg.currentLOD = ship->currentLOD;
    dummyTarg.collMyBlob = ship->collMyBlob;
    vecSet(dummyTarg.posinfo.velocity,0.0f,0.0f,0.0f);

    //track target even more precisely
    vecSub(heading,spec->burstFireVector,ship->posinfo.position);
    vecNormalize(&heading);
    aitrackHeadingWithFlags(ship,&heading,0.9999f,AITRACKHEADING_IGNOREUPVEC);

    //set special information that needs to be 'transmitted'
    //to the code in gunshoot.

    //fix later
    spec->bulletLifeTime = range*oneOverburstSpeed;



    bitSet(ship->specialFlags,SPECIAL_BurstFiring);
    done = gunShootGunsAtTarget(ship,&dummyTarg,0.0f,&trajectory);
    bitClear(ship->specialFlags,SPECIAL_BurstFiring);
    if(done == TRUE)
    {
        spec->cooldown = TRUE;
        spec->burstChargeState2 = burstCoolDownTime;
    }
    return done;
}
void GenericDefenderAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist)
{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;
    GenericDefenderStatics *defenderstat = (GenericDefenderStatics *)shipstaticinfo->custstatinfo;
    real32 newrange;
    //newrange = maxdist - defenderstat->gunRange;
    //newrange = defenderstat->gunRange - newrange;
    //newrange = defenderstat->gunRange - maxdist + defenderstat->gunRange;
    //could do check if maxdist == gunRange, then don't do calcs, just use
    //max dist

    vector trajectory;
    real32 dist;
    real32 range;
    real32 temp;
    real32 rightvelocity;
    vector right;

    newrange = (defenderstat->gunRange[ship->tacticstype]*2) - maxdist;
    if(newrange < 0.0f)
        newrange = defenderstat->tooCloseRange[ship->tacticstype] + 100.0f;
    else if(newrange > defenderstat->gunRange[ship->tacticstype])
    {
        newrange = defenderstat->gunRange[ship->tacticstype];
    }

    switch (ship->aistateattack)
    {
        case 0:
            ship->aistateattack = DEFENDER_APPROACH;
            // fall through to DEFENDER_APPROACH

        case DEFENDER_APPROACH:
            aishipGetTrajectory(ship,target,&trajectory);
            dist = fsqrt(vecMagnitudeSquared(trajectory));
            range = RangeToTargetGivenDist(ship,target,dist);
            if (range > newrange)
            {
                aishipFlyToShipAvoidingObjsWithVel(ship,target,AISHIP_FastAsPossible|AISHIP_PointInDirectionFlying,0.0f,&target->posinfo.velocity);
                break;
            }
#ifdef DEBUG_DEFENDER
            dbgMessagef("\n%x Changing to circle",ship);
#endif
            ship->aistateattack = DEFENDER_CIRCLE;
            goto circleAlreadyCalculatedTrajectory;

        case DEFENDER_CIRCLE:
            aishipGetTrajectory(ship,target,&trajectory);
            dist = fsqrt(vecMagnitudeSquared(trajectory));
            range = RangeToTargetGivenDist(ship,target,dist);
            if (range > newrange)
            {
#ifdef DEBUG_DEFENDER
            dbgMessagef("\n%x Changing back to approach",ship);
#endif
                ship->aistateattack = DEFENDER_APPROACH;
                break;
            }
circleAlreadyCalculatedTrajectory:

            vecDivideByScalar(trajectory,dist,temp);

            aitrackHeading(ship,&trajectory,FLYSHIP_ATTACKACCURACY);

            matGetVectFromMatrixCol2(right,ship->rotinfo.coordsys);
            rightvelocity = vecDotProduct(right,ship->posinfo.velocity);

            if (rightvelocity < defenderstat->CIRCLE_RIGHT_VELOCITY)
            {
                physApplyForceToObj((SpaceObj *)ship,ship->nonstatvars.thruststrength[TRANS_RIGHT]*defenderstat->CIRCLE_RIGHT_THRUST,TRANS_RIGHT);
            }

            if (range < defenderstat->tooCloseRange[ship->tacticstype])
            {
                aitrackZeroForwardVelocity(ship);
            }

            if (ship->attackvars.multipleAttackTargets)
            {
                gunShootGunsAtMultipleTargets(ship);
            }
            else
            {
                gunShootGunsAtTarget(ship,target,range,&trajectory);
            }

            break;

        default:
            dbgAssert(FALSE);
            break;
    }

//    attackStraightForward(ship,target,newrange,defenderstat->tooCloseRange[ship->tacticstype]);
}
void doKamikazeAttack(Ship *ship,SpaceObjRotImpTarg *target)
{
    real32 mag,dist,range,shipvel;
    vector destination,trajectory,heading,shipheading,EinsteinVelocity;
    ShipStaticInfo *shipstaticinfo = ship->staticinfo;

    vecSub(trajectory,target->collInfo.collPosition,ship->posinfo.position);
    mag = vecMagnitudeSquared(trajectory);
    dist = fsqrt(mag);

    destination = trajectory;
    vecNormalize(&destination);
    heading = destination;

    //this hokey fudge factor is needed so the kamikaze ship doesn't
    //slow down as it reaches its destination
    mag = dist + 500.0f;
    vecScalarMultiply(destination,destination,mag);
    vecAddTo(destination,target->collInfo.collPosition);

    range = RangeToTargetGivenDist(ship,target,dist);

    switch(ship->kamikazeState)
    {
    case K_Start:
        //if within a threshold range
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        if(range < 500.0f)
        {
            //calculate flyby dist
            matGetVectFromMatrixCol3(shipheading, ship->rotinfo.coordsys);
            vecScalarMultiply(shipheading,shipheading,kamikazeFlyByDist);
            vecAdd(ship->kamikazeVector,shipheading,target->collInfo.collPosition);
            ship->kamikazeState = K_TurnAround;
        }
        ship->kamikazeState = K_Ram;

        break;

    case K_Ram:
        if (range < 400.0f)
        {
            ship->kamikazeState = K_Yell;
        }
    case K_Ram2:
        //lets use...mmmmm..twister theor...no...relativity
        vecSub(EinsteinVelocity,ship->posinfo.velocity,target->posinfo.velocity);
        shipvel = fsqrt(vecMagnitudeSquared(EinsteinVelocity));
        if(ship->shiptype == MinelayerCorvette)
        {
            ((MinelayerCorvetteSpec *)(ship->ShipSpecifics))->mineaistate = MINE_DROP_ATTACK;
        }
        else if (ship->shiptype == DefenseFighter)
        {
            goto dontshoot;
        }

        if (isShipStaticInterceptor(shipstaticinfo))
        {
            if (range < shipstaticinfo->bulletRange[ship->tacticstype])
            {
                GenericInterceptorStatics *interceptorstat = (GenericInterceptorStatics *)shipstaticinfo->custstatinfo;
                uword targetIndex;

                if (target->objtype == OBJ_ShipType)
                {
                    targetIndex = (uword)((ShipStaticInfo *)target->staticinfo)->shipclass;
                }
                else
                {
                    targetIndex = (uword)NUM_CLASSES;
                }

                if (GenericInterceptorCanFire(ship,target,&trajectory,interceptorstat->triggerHappy[ship->tacticstype][targetIndex]))
                {
                    ship->staticinfo->custshipheader.CustShipFire(ship,target);
                }
            }
        }
        else
        {
            gunShootGunsAtTarget(ship,target,range,&trajectory);
        }
dontshoot:
        aishipFlyToPointAvoidingObjs(ship,&destination,AISHIP_PointInDirectionFlying | AISHIP_FirstPointInDirectionFlying | AISHIP_FastAsPossible,0.0f);
        if(range < 1500.0f)
        {
            bitSet(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        }
        else
        {
            bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        }

/*
        if(range < 400.0f && (shipvel < ship->staticinfo->staticheader.maxvelocity*0.7f ||
                   vecDotProduct(trajectory,heading) < 0))
        {
            //ship is inside 400.0f, and isn't faceing ship, or isn't
            //going fast enough

            //calculate flyby dist
            matGetVectFromMatrixCol3(shipheading, ship->rotinfo.coordsys);
            vecScalarMultiply(shipheading,shipheading,kamikazeFlyByDist);
            vecAdd(ship->kamikazeVector,shipheading,target->posinfo.position);
            ship->kamikazeState = K_TurnAround;
        }
*/
        break;
    case K_TurnAround:
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        aishipFlyToPointAvoidingObjs(ship,&ship->kamikazeVector,AISHIP_PointInDirectionFlying | AISHIP_FirstPointInDirectionFlying | AISHIP_FastAsPossible,0.0f);
        if(MoveReachedDestinationVariable(ship,&ship->kamikazeVector,300.0f))
            ship->kamikazeState = K_TurnAround2;
        break;
    case K_TurnAround2:
        bitClear(ship->specialFlags,SPECIAL_KamikazeCrazyFast);
        if(aitrackHeadingWithFlags(ship,&heading,0.90f,AITRACKHEADING_IGNOREUPVEC))
            ship->kamikazeState = K_Ram;
        break;
    case K_Yell:
//      speechEvent(ship, COMM_LInt_Kamikaze, 0);
        battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_Kamikaze, ship, SOUND_EVENT_DEFAULT);
        ship->kamikazeState = K_Ram2;
        break;
    }

        //fire guns here...
    //
    //
    //Sound note:   Could put in kamikaze state change here after
    //              getting to within a certain distance of target
    //
    //          ask bryce how to...
}
void defensefightertargetbullet(Ship *ship, Bullet *bullettotarget)
{
    DefenseFighterSpec *spec = (DefenseFighterSpec *)ship->ShipSpecifics;
    DefenseFighterStatics *defensefighterstatics;
    DefenseStruct *newdefensestruct;
    Bullet *laser;
    GunStatic *gunstatic;
    Gun *gun;
    ShipStaticInfo *shipstatic;
    vector positionInWorldCoordSys,tempvec;
    real32 floatDamage;
    udword intDamage;
    udword intVelocity;
    udword intLength;
    etgeffectstatic *stat;
    etglod *etgLOD;
    sdword LOD;
    Effect *newEffect;

#ifdef HW_BUILD_FOR_DEBUGGING
/*    dbgMessagef("B: %d %x %x %f %f %f %x %f %x",universe.univUpdateCounter,
                                    bullettotarget->flags,
                                    bullettotarget->owner,
                                    bullettotarget->timelived,
                                    bullettotarget->damage,
                bullettotarget->damageFull,
                bullettotarget->SpecialEffectFlag,
                bullettotarget->BulletSpeed,
                bullettotarget);
*/
#endif
    gun = &ship->gunInfo->guns[0];
    gunstatic = gun->gunstatic;
    shipstatic = (ShipStaticInfo *)ship->staticinfo;
    defensefighterstatics = (DefenseFighterStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    bitSet(bullettotarget->SpecialEffectFlag, 0x0002);   //set the flag

    laser = memAlloc(sizeof(Bullet),"Bullet",0);
    memset(laser,0,sizeof(Bullet));      // for safety

    laser->objtype = OBJ_BulletType;
    laser->flags = 0;
    laser->staticinfo = NULL;
    ClearNode(laser->renderlink);
    laser->currentLOD = ship->currentLOD;
    laser->cameraDistanceSquared = ship->cameraDistanceSquared;

    laser->soundType = gunstatic->gunsoundtype;
    laser->bulletType = BULLET_Laser;
    laser->owner = ship;
    laser->gunowner = gun;
    laser->target = NULL;

    laser->bulletColor = etgBulletColor[shipstatic->shiprace][laser->soundType];

    laser->bulletmass = 0.0f; //gunstatic->bulletmass;
    laser->lengthmag = 600.0f;
    laser->damage = frandombetween(defensefighterstatics->DamageReductionLow,
                                     defensefighterstatics->DamageReductionHigh);
    laser->timelived = 0.0f;
    laser->totallifetime = 100.0f;  //laser will only live for a sec anyways...
    laser->SpecialEffectFlag = 0;
    laser->traveldist = gunstatic->bulletlength;
    laser->beamtraveldist = gunstatic->bulletlength;

    //SET_MOVING_LINEARLY(laser->posinfo.isMoving);
    //laser->posinfo.haventCalculatedDist = TRUE;
    laser->DFGFieldEntryTime = 0.0f;

    matMultiplyMatByVec(&positionInWorldCoordSys,&ship->rotinfo.coordsys,&gunstatic->position);
    vecAdd(laser->posinfo.position,positionInWorldCoordSys,ship->posinfo.position);
    vecSub(laser->lengthvec, bullettotarget->posinfo.position, laser->posinfo.position);
    // heading
    tempvec = laser->lengthvec;
    vecNormalize(&tempvec);

    //matMultiplyMatByVec(&gunheadingInWorldCoordSys, &ship->rotinfo.coordsys, &tempvec);
    //laser->bulletheading = gunheadingInWorldCoordSys;
    laser->bulletheading = tempvec;
    matCreateCoordSysFromHeading(&laser->rotinfo.coordsys,&tempvec);

    vecZeroVector(laser->posinfo.velocity);

    //Laser effect...
    floatDamage = (real32)laser->damage;
    intDamage = TreatAsUdword(floatDamage);
    intVelocity = TreatAsUdword(gunstatic->bulletspeed);
    intLength = TreatAsUdword(gunstatic->bulletlength);
    //create an effect for bullet, if applicable

    etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunBullet];//get pointer to bullet effect
    //etgLOD = etgGunEventTable[0][gunstatic->gunsoundtype][EGT_GunBullet];//get pointer to bullet effect
  //in future change back to proper one above...
    if (etgLOD != NULL)
    {
        if (bullettotarget != NULL)
        {
          LOD = min(ship->currentLOD, bullettotarget->currentLOD);
        }
        else
        {
          LOD = ship->currentLOD;
        }
        if (LOD >= etgLOD->nLevels)
        {
          stat = NULL;
        }
        else
        {
          stat = etgLOD->level[LOD];
        }
    }
    else
    {
      stat = NULL;
    }
#if ETG_DISABLEABLE
    if (stat != NULL && etgBulletEffectsEnabled && etgEffectsEnabled && !etgFrequencyExceeded(stat))
#else
    if (stat != NULL && etgBulletEffectsEnabled && !etgFrequencyExceeded(stat))
#endif
    {
        laser->effect = etgEffectCreate(stat, laser, NULL, NULL, NULL, 1.0f, EAF_AllButNLips, 3, intDamage, intVelocity, intLength);
//        univAddObjToRenderListIf((SpaceObj *)laser->effect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
        //do length calculations :)
        ((real32 *)laser->effect->variable)[ETG_LengthVariable] =
                    fsqrt(vecMagnitudeSquared(laser->lengthvec));
    }
    else
    {
        laser->effect = NULL;                              //play no effect for this bullet
    }

//    laser->effect = NULL;               //need for render...add later?

    laser->hitEffect = etgGunEventTable[shipstatic->shiprace][bullettotarget->gunowner->gunstatic->gunsoundtype][EGT_BulletDestroyed];//get pointer to bullet effect

    if (ship->soundevent.burstHandle < 0)
    {
        soundEventBurstFire(ship, gun);
    }

    etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunFire];//get pointer to bullet effect
    if (etgLOD != NULL)
    {
        LOD = ship->currentLOD;
        if (LOD >= etgLOD->nLevels)
        {
            stat = NULL;
        }
        else
        {
            stat = etgLOD->level[LOD];
        }
    }
    else
    {
        stat = NULL;
    }

#if ETG_DISABLEABLE
    if (stat != NULL && etgEffectsEnabled && etgFireEffectsEnabled && !etgFrequencyExceeded(stat))
#else
    if (stat != NULL && etgFireEffectsEnabled && !etgFrequencyExceeded(stat))
#endif
    {                                                       //if there is a gun fire effect
        newEffect = etgEffectCreate(stat, laser, NULL, NULL, NULL, 1.0f, EAF_AllButNLips, 1, intDamage);
//        univAddObjToRenderListIf((SpaceObj *)newEffect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
    }
/*
//spawn bullet hitting effect
    etgLOD = etgTractorBeamEffectTable[ship->shiprace];

    //etgLOD = etgGunEventTable[shipstatic->shiprace][gunstatic->gunsoundtype][EGT_GunFire];//get pointer to bullet effect
    if (etgLOD != NULL)
    {
        LOD = ship->currentLOD;
        if (LOD >= etgLOD->nLevels)
        {
            stat = NULL;
        }
        else
        {
            stat = etgLOD->level[LOD];
        }
    }
    else
    {
        stat = NULL;
    }

#if ETG_DISABLEABLE
    if (stat != NULL && etgEffectsEnabled)
#else
    if (stat != NULL)
#endif
    {                                                       //if there is a gun fire effect
//        size = etgEffectSize(stat->nParticleBlocks);//compute size of effect
        size = stat->effectSize;
        newEffect = memAlloc(size, "DefenseFHittingEffect", 0);          //allocate the new effect

        newEffect->objtype = OBJ_EffectType;
        newEffect->flags = SOF_Rotatable | SOF_AttachVelocity | SOF_AttachPosition | SOF_AttachCoordsys;
        newEffect->staticinfo = (StaticInfo *)stat;
        ClearNode(newEffect->renderlink);
        newEffect->currentLOD = LOD;
        newEffect->cameraDistanceSquared = ship->cameraDistanceSquared;

        newEffect->timeElapsed = 0.0f;                          //brand new heavies

        floatDamage = 30.0f;
        intDamage = TreatAsUdword(floatDamage);

        newEffect->rotinfo.coordsys = bullettotarget->rotinfo.coordsys;
        newEffect->posinfo.position = bullettotarget->posinfo.position; //start at same spot as bullet
        newEffect->posinfo.velocity = bullettotarget->posinfo.velocity; //start at same spot as bullet
        etgEffectCodeStart(stat, newEffect, 1, intDamage);//get the code a-runnin'
        SET_MOVING_IMMOBILE(newEffect->posinfo.isMoving);
        newEffect->posinfo.haventCalculatedDist = TRUE;
        univUpdateObjRotInfo((SpaceObjRot *)newEffect);

//        newEffect->owner = NULL;                               // nothing owns this effect
        newEffect->owner = (Ship *) bullettotarget;
        listAddNode(&universe.SpaceObjList,&(newEffect->objlink),newEffect);
        univAddObjToRenderListIf((SpaceObj *)newEffect,(SpaceObj *)ship);     // add to render list if parent ship is in render list
    }
*/
    //Not sure If I need to add...

    listAddNode(&universe.SpaceObjList,&(laser->objlink),laser);
    listAddNode(&universe.BulletList,&(laser->bulletlink),laser);
    univAddObjToRenderListIf((SpaceObj *)laser,(SpaceObj *)ship);     // add to render list if parent ship is in render list

    newdefensestruct = memAlloc(sizeof(DefenseStruct),"DS(DefenseStruct)",Pyrophoric);
    newdefensestruct->bullet = bullettotarget;
    newdefensestruct->CoolDown = FALSE;
    newdefensestruct->CoolDownTime = 0.0f;
    newdefensestruct->LaserDead = FALSE;
    listAddNode(&spec->DefenseList,&newdefensestruct->bulletnode,newdefensestruct);
    newdefensestruct->laser = laser;



    if(bitTest(ship->flags,SOF_CloakGenField))
    {
        bitSet(ship->flags,SOF_DeCloaking);
        bitClear(ship->flags,SOF_Cloaked);
        bitClear(ship->flags,SOF_Cloaking);
    }
}
void defenseFighterAdjustLaser(Bullet *laser)
{       //calculates laser direction n' such for rendering...
    DefenseFighterSpec *spec;
 //   DefenseFighterStatics *defensefighterstatics;
    Node *bulletnode;
    DefenseStruct *defensestruct;
    Ship *ship;

    vector tempvec;
    GunStatic *gunstatic;
    Gun *gun;

    vector positionInWorldCoordSys;

    if(laser->owner == NULL)
        return;

    ship = laser->owner;

    gun = &ship->gunInfo->guns[0];
    gunstatic = gun->gunstatic;


    spec= (DefenseFighterSpec *)ship->ShipSpecifics;

//    defensefighterstatics = (DefenseFighterStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    bulletnode = spec->DefenseList.head;

    while (bulletnode != NULL)
    {   //as long as theres a bullet to deal with
        defensestruct = (DefenseStruct *)listGetStructOfNode(bulletnode);
        if(defensestruct->LaserDead == TRUE)
        {
            bulletnode = bulletnode->next;
            continue;
        }
        if(laser == defensestruct->laser)
        {
            dbgAssertOrIgnore(defensestruct->bullet != NULL);
            matMultiplyMatByVec(&positionInWorldCoordSys,&ship->rotinfo.coordsys,&gunstatic->position);
            vecAdd(laser->posinfo.position,positionInWorldCoordSys,ship->posinfo.position);
            vecSub(laser->lengthvec, defensestruct->bullet->posinfo.position, laser->posinfo.position);

            // heading
            tempvec = defensestruct->laser->lengthvec;
            vecNormalize(&tempvec);

            //matMultiplyMatByVec(&gunheadingInWorldCoordSys, &ship->rotinfo.coordsys, &tempvec);
            //laser->bulletheading = gunheadingInWorldCoordSys;
            defensestruct->laser->bulletheading = tempvec;
            matCreateCoordSysFromHeading(&defensestruct->laser->rotinfo.coordsys,&tempvec);
            if(defensestruct->laser->effect != NULL)
            {    //adjust length
                ((real32 *)defensestruct->laser->effect->variable)[ETG_LengthVariable] =
                    fsqrt(vecMagnitudeSquared(defensestruct->laser->lengthvec));
            }
            return;
        }
        bulletnode = bulletnode->next;
    }
    //we shouldn't get to this point :)
    //dbgMessagef("Laser Drawn doesn't exist in defense fighter records.");

    //on further reflection..if we kill the laster...but it doesn't go bye bye, we might get here...
}
void DefenseFighterHouseKeep(Ship *ship)
{
    DefenseFighterSpec *spec = (DefenseFighterSpec *)ship->ShipSpecifics;
    DefenseFighterStatics *defensefighterstatics;
    Node *bulletnode;
    Node *tempnode;
    DefenseStruct *defensestruct;
    vector seperationvector;
    vector tempvec,rot_vector;
    GunStatic *gunstatic;
    Gun *gun;

    vector positionInWorldCoordSys;
    gun = &ship->gunInfo->guns[0];
    gunstatic = gun->gunstatic;

    defensefighterstatics = (DefenseFighterStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    bulletnode = spec->DefenseList.head;

    while (bulletnode != NULL)
    {   //as long as theres a bullet to deal with
        defensestruct = (DefenseStruct *)listGetStructOfNode(bulletnode);

/*        if (defensestruct->bullet)
            dbgMessagef("DS: %d %f %d %f %d %d",
                        universe.univUpdateCounter,
                        defensestruct->bullet->collOptimizeDist,
                        defensestruct->laser ? 1:0,
                        defensestruct->CoolDownTime,
                        defensestruct->CoolDown ? 1:0,
                        defensestruct->LaserDead ? 1:0);
        else
            dbgMessagef("DS: %d N  %d %f %d %d",
                        universe.univUpdateCounter,
                        defensestruct->laser ? 1:0,
                        defensestruct->CoolDownTime,
                        defensestruct->CoolDown ? 1:0,
                        defensestruct->LaserDead ? 1:0);*/

        if(!defensestruct->CoolDown)
        {   //laser cannon isn't cooling down, so continue tracking
            if (defensestruct->bullet == NULL || defensestruct->bullet->damage <= 0)
            {    //bullet is already dead...don't kill it again
                defensestruct->bullet = NULL;   //destroy pointer...
                if (defensestruct->laser != NULL)
                {
                    defensestruct->laser->timelived =10000.0f; //kill laser
                }
                defensestruct->LaserDead = TRUE;    //set killed flag
                defensestruct->laser=NULL;
                defensestruct->CoolDown = TRUE;     //begin laser cooldown
                defensestruct->CoolDownTime = 0.0f;    //reset to 0 for cooldown count
                bulletnode=bulletnode->next;
                continue;
            }
            if((universe.univUpdateCounter & defensefighterstatics->DamageRate) == 0)
            {
                // Time to do damage...
                //Do damage to bullet
                defensestruct->bullet->damage = (defensestruct->bullet->damage - frandombetween(defensefighterstatics->DamageReductionLow,defensefighterstatics->DamageReductionHigh));
                if(defensestruct->bullet->damage <= 0)
                {
                    //bullet is destroyed
                    DefenseFighterDestroyedABullet(ship, defensestruct->bullet, defensestruct->laser);
                    defensestruct->bullet->damage = 0;      //cap at 0;
                    defensestruct->bullet = NULL;   //destroy pointer...
                    //dbgMessagef("Defense Fighter Destroyed A Bullet.");
                    if (defensestruct->laser != NULL)
                    {
                        defensestruct->laser->timelived =10000.0f; //kill laser
                    }
                    defensestruct->LaserDead = TRUE;    //set killed flag
                    if(defensestruct->laser->effect != NULL)
                    {
                        univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect);
                    }
                    defensestruct->laser=NULL;
                    defensestruct->CoolDown = TRUE;     //begin laser cooldown
                    defensestruct->CoolDownTime = 0.0f;    //reset to 0 for cooldown count
                }
            }
            if(defensestruct->laser != NULL)
            {
                //check if bullet is still in range and infront...
                if((universe.univUpdateCounter & defensefighterstatics->RangeCheckRate) == 0)
                {
                    //time to check if in front
                    vecSub(seperationvector, ship->posinfo.position, defensestruct->bullet->posinfo.position);
                    if(vecMagnitudeSquared(seperationvector) > ship->staticinfo->bulletRangeSquared[ship->tacticstype])
                    {
                        //bullet is out of range
                        defensestruct->laser->timelived =10000.0f; //kill laser
                        defensestruct->LaserDead = TRUE;    //set killed flag
                        if(defensestruct->laser->effect != NULL)
                        {
                            univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect);
                        }
                        defensestruct->laser=NULL;
                        //dbgMessagef("Bullet out of range.");
                        bitClear(defensestruct->bullet->SpecialEffectFlag,0x0002);
                        defensestruct->CoolDown = TRUE;     //begin laser cooldown
                        defensestruct->bullet = NULL;       //set target to NULL so it isn't referenced again!
                        defensestruct->CoolDownTime = 0.0f;    //reset to 0 for cooldown count
                    }
                    else if(!defensefighterCheckInFront(ship, defensestruct->bullet))
                    {
                        //if bullet ISN'T in front
                        defensestruct->laser->timelived =10000.0f; //kill laser
                        defensestruct->LaserDead = TRUE;    //set killed flag
                        if(defensestruct->laser->effect != NULL)
                        {
                            univRemoveObjFromRenderList((SpaceObj *) defensestruct->laser->effect);
                        }
                        defensestruct->laser=NULL;
                        //dbgMessagef("Bullet Not infront anymore...stop tracking.");
                        if(defensefighterstatics->MultipleTargettingofSingleBullet)
                        {
                            bitClear(defensestruct->bullet->SpecialEffectFlag,0x0002);
                        }
                        defensestruct->CoolDown = TRUE;     //begin laser cooldown
                        defensestruct->bullet = NULL;       //set target to NULL so it isn't referenced again!
                        defensestruct->CoolDownTime = 0.0f;    //reset to 0 for cooldown count
                    }

                }
            }
            //This code is for the sake of the visual effect which STILL won't work
            //properly!!!  So it is temperary only!
            if(defensestruct->laser != NULL)
            {   //update bullent info...for visual effect
                dbgAssertOrIgnore(defensestruct->bullet != NULL);
                matMultiplyMatByVec(&positionInWorldCoordSys,&ship->rotinfo.coordsys,&gunstatic->position);
                vecAdd(defensestruct->laser->posinfo.position,positionInWorldCoordSys,ship->posinfo.position);
                vecSub(defensestruct->laser->lengthvec, defensestruct->bullet->posinfo.position, defensestruct->laser->posinfo.position);

                // heading
                tempvec = defensestruct->laser->lengthvec;
                vecNormalize(&tempvec);

                //matMultiplyMatByVec(&gunheadingInWorldCoordSys, &ship->rotinfo.coordsys, &tempvec);
                //laser->bulletheading = gunheadingInWorldCoordSys;
                defensestruct->laser->bulletheading = tempvec;
                matCreateCoordSysFromHeading(&defensestruct->laser->rotinfo.coordsys,&tempvec);
                if(defensestruct->laser->effect != NULL)
                {    //adjust length
                    ((real32 *)defensestruct->laser->effect->variable)[ETG_LengthVariable] =
                        fsqrt(vecMagnitudeSquared(defensestruct->laser->lengthvec));
                }
            }

        }
        else
        {    //this laser cannon is cooling, so cool it
            defensestruct->CoolDownTime += universe.phystimeelapsed;
            if(defensestruct->CoolDownTime > defensefighterstatics->CoolDownTimePerLaser)
            {    //Laser Terminal has cooled down...so free it up
                tempnode = bulletnode->next;
                listDeleteNode(bulletnode);
                //dbgMessagef("Deleting defense node in CoolDown.");
                bulletnode = tempnode;
                continue;
            }
        }
        bulletnode = bulletnode->next;
    }

    if (spec->DefenseList.num == 0)
    {
        soundEventBurstStop(ship, gun);
    }

    //do special rotation if neccessary
    if(bitTest(ship->dontrotateever,1))
    {
        //matGetVectFromMatrixCol3(rot_vector,ship->rotinfo.coordsys);
        vecSet(rot_vector,100.0f,0.0f,0.0f);
        vecAddTo(ship->rotinfo.torque, rot_vector);
        vecCapVectorSloppy(&ship->rotinfo.rotspeed, defensefighterstatics->max_rot_speed );
        spec->rotate_time_counter -= universe.phystimeelapsed;
        if(spec->rotate_time_counter <= 0.0f)
        {
            bitClear(ship->dontrotateever,1);
            spec->DefenseFighterCanNowRotate = FALSE;
        }
    }
    else if (spec->DefenseFighterCanNowRotate == FALSE)
    {
        spec->rotate_time_counter += universe.phystimeelapsed;
        if(spec->rotate_time_counter >= defensefighterstatics->rotate_recover_time)
        {
            spec->DefenseFighterCanNowRotate = TRUE;
            spec->rotate_time_counter = defensefighterstatics->rotate_time;
        }

    }

}
void P2MultiBeamFrigateAttackDoAttack(Ship *ship,SpaceObjRotImpTarg *target,real32 maxdist,bool PassiveAttack)

{
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;

    P2MultiBeamFrigateStatics *frigstat = (P2MultiBeamFrigateStatics *)shipstaticinfo->custstatinfo;
    P2MultiBeamFrigateSpec    *spec     = (P2MultiBeamFrigateSpec *)ship->ShipSpecifics;

    vector trajectory;
    vector shipRightVec;
    real32 range;

        spec->aiattacklast = universe.totaltimeelapsed;
    ship->autostabilizeship = FALSE;

    aishipGetTrajectory(ship, target, &trajectory);
    range = RangeToTarget(ship,target,&trajectory);

    if (range > frigstat->MultiBeamRange[ship->tacticstype])
    {
        //not in range
        if(!PassiveAttack)
        {
            //do aiship fly to stuff here

            //if not in range...fly to the ship
            //else track zero velocity
                aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
        }
        return;
    }

    //we are in range

    vecNormalize(&trajectory);
    if(!PassiveAttack)
	{
		aitrackZeroVelocity(ship);
	}
    matGetVectFromMatrixCol2(shipRightVec,ship->rotinfo.coordsys);

    aitrackHeadingAndUp(ship,&trajectory,&shipRightVec,0.9999f);

    
	if(vecMagnitudeSquared(ship->rotinfo.rotspeed) > frigstat->AttackRotationSpeed)
    {
		if(aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC|AITRACK_DONT_ZERO_ME))
		{
			//rotation speed reached
			//lets fire guns if we can
			P2MultiBeamFrigateFire(ship,target);
		}
    }

/*  OLD SCHOOL CODE  */

    /*
    switch (ship->aistateattack)
    {
        case STATE_INIT:
            // deliberatly fall through to state_approach
//            spec->steady = FALSE;
            ship->aistateattack=STATE_APPROACH;
        case STATE_APPROACH:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_APPROACH", (udword)ship);
#endif
            if (spec->spining)
            {
                ship->aistateattack = STATE_SPINDOWN;
                break;
            }

            aishipGetTrajectory(ship, target, &trajectory);

            range = RangeToTarget(ship,target,&trajectory);

            if (range < frigstat->MultiBeamRange[ship->tacticstype] || PassiveAttack)
            {
                temp = trajectory;
                temp.z+=5;
                temp.y+=5;
                temp.x+=5;

                //vecCrossProduct(heading,trajectory,temp);

                //vecNormalize(&heading);
                vecNormalize(&trajectory);

				if(!PassiveAttack)
				{
					aitrackZeroVelocity(ship);
				}


                if (aitrackHeadingWithFlags(ship,&trajectory,0.99f,AITRACKHEADING_IGNOREUPVEC))
                {
                    ship->aistateattack = STATE_SPINUP;
                    //get up vector
                    matGetVectFromMatrixCol1(temp,ship->rotinfo.coordsys);
                    aitrackForceHeading(ship,&trajectory,&temp);
                }
            }
            else
            {
				aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying + AISHIP_CarTurn,0.0f);
			}
            break;
        case STATE_SPINUP:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_SPINUP", (udword)ship);
#endif
            desiredrotspeed = frigstat->AttackRotationSpeed;

			if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
            aitrackHeadingAndUp(ship,&heading,&shipRightVec,0.99f);

			if (aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW))
            {
                ship->aistateattack = STATE_FIRE;
                spec->spining = TRUE;
                spec->aifirestarttime = universe.totaltimeelapsed + frigstat->BeamFireTime;
            }

            break;
        case STATE_FIRE:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_FIRE", (udword)ship);
#endif
            shipstaticinfo->custshipheader.CustShipFire(ship, target);

            if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
			aishipGetTrajectory(ship,target,&trajectory);

            range = RangeToTarget(ship,target,&trajectory);

            if (range > frigstat->MultiBeamRange[ship->tacticstype])
                ship->aistateattack = STATE_INIT;

            temp = trajectory;
            temp.z+=5;
            temp.y+=5;
            temp.x+=5;

            vecCrossProduct(heading,trajectory,temp);

            vecNormalize(&heading);
            vecNormalize(&trajectory);

            //if (aitrackHeadingWithFlags(ship,&heading,0.99f,AITRACKHEADING_IGNOREUPVEC))
          //  {
        //        ship->aistateattack = STATE_INIT;
      //      }
            desiredrotspeed = frigstat->AttackRotationSpeed;
            aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW);

			if(universe.totaltimeelapsed > spec->aifirestarttime)
			{
                //fire time up!  start spindown
				ship->aistateattack = STATE_SPINDOWN;
				spec->aifirestarttime = universe.totaltimeelapsed + frigstat->fireDownTime;
			}
            break;
        case STATE_SPINDOWN:
#ifdef DEBUG_FRIGATEATTACK
            dbgMessagef("\nShip %x STATE_SPINDOWN", (udword)ship);
#endif
            desiredrotspeed = 0;

            if(!PassiveAttack)
			{
				aitrackZeroVelocity(ship);
			}
			if (aitrackRotationSpeed(ship,desiredrotspeed,ROT_ABOUTZCCW) &&
				universe.totaltimeelapsed > spec->aifirestarttime)
            {
                ship->aistateattack = STATE_INIT;
                spec->spining = FALSE;
            }
            break;
    }
    */
}
Example #15
0
void CloakGeneratorHouseKeep(Ship *ship)
{
    CloakGeneratorSpec *spec = (CloakGeneratorSpec *)ship->ShipSpecifics;
    CloakGeneratorStatics *cloakgeneratorstatics;
    Node *cloaknode, *temp;
    SpaceObj *spaceobj;
    CloakStruct *cloakstruct;

    vector diff;
    real32  distanceSqr;

    cloakgeneratorstatics = (CloakGeneratorStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    if(spec->CloakOn == TRUE)       //Cloaking Generator is On
    {
        //15th frame..so do a search on other ships within 'proximity'
        if ((universe.univUpdateCounter & CLOAKGENERATOR_CLOAKCHECK_RATE) == (ship->shipID.shipNumber & CLOAKGENERATOR_CLOAKCHECK_RATE))
        {
            CloakAddObjectsInProximity(ship);   //this opp is slow!  So maybe decrease frequency
        }

        //decrement functionality time
        spec->CloakStatus -= universe.phystimeelapsed;

        if ((spec->CloakStatus <= 10.0f) && !spec->CloakLowWarning)
        {
            spec->CloakLowWarning = TRUE;
//            speechEvent(ship, STAT_Cloak_CloakPowerLow, (sdword)spec->CloakStatus);
            if (battleCanChatterAtThisTime(BCE_CloakingPowerLow, ship))
            {
                battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_CloakingPowerLow, ship, (sdword)spec->CloakStatus);
            }
        }

        //Cloak Field has been on too long
        if(spec->CloakStatus <= 0.0f)
        {
            DeCloakAllObjects(ship);  //decloak everything
            spec->CloakOn = FALSE;    //reset flags
            spec->CloakStatus = 0.0f; //reset CloakStatus
            spec->CloakLowWarning = FALSE;  //reset flag
//            soundEvent(ship, PowerOff);
//            speechEvent(ship, COMM_Cloak_Decloak, 0);
            if (battleCanChatterAtThisTime(BCE_Decloaking, ship))
            {
                battleChatterAttempt(SOUND_EVENT_DEFAULT, BCE_Decloaking, ship, SOUND_EVENT_DEFAULT);
            }
        }
    }
    else        //cloak field is off
    {
        //recharge cloaking juice at tunable rate
        spec->CloakStatus +=  universe.phystimeelapsed*cloakgeneratorstatics->ReChargeRate;
        if(spec->CloakStatus >= cloakgeneratorstatics->MaxCloakingTime)
        {
            spec->CloakStatus = cloakgeneratorstatics->MaxCloakingTime; //cap max cloaking juice
        }
    }

    //perform maintainence on cloaked ships (cloaking,decloaking and continual cloak)
    cloaknode = spec->CloakList.head;
    while(cloaknode != NULL)
    {
        cloakstruct = (CloakStruct *)listGetStructOfNode(cloaknode);
        spaceobj = cloakstruct->spaceobj;

        // wierd crash ...

		if (spaceobj==NULL) 
		{
			temp = cloaknode;
			cloaknode = cloaknode->next;

			listDeleteNode(temp);
			continue;
		}
		
		//if spaceobj is dead for some reason, remove its references and stop bothering with it
        if (bitTest(spaceobj->flags,SOF_Dead))
        {   //dead so get rid of quickly...
            cloaknode=cloaknode->next;                  //we're about to delete this node so move to next
            CloakGeneratorRemoveShipReferences(ship,(Ship *)spaceobj);  //delete everything about it
            continue;
        }

        //perform a change check!
        //this seems like a waste because we are AGAIN calculating distances.  Do better later!
        if ((universe.univUpdateCounter & CLOAKGENERATOR_CLOAKCHECK_RATE) == (ship->shipID.shipNumber & CLOAKGENERATOR_CLOAKCHECK_RATE))
        {
            vecSub(diff,spaceobj->posinfo.position,ship->posinfo.position);
            distanceSqr = vecMagnitudeSquared(diff);

            if(distanceSqr > cloakgeneratorstatics->CloakingRadiusSqr)     //maybe add fuzzy logic so thing doesn't always pop in and out in and out in and out...
            {
                if(bitTest(spaceobj->flags,SOF_Cloaked))
                {
                    bitClear(spaceobj->flags,SOF_Cloaked);
                    if(spaceobj->objtype == OBJ_ShipType)
                    {
                        //if object was a ship set objects decloaking time for cloak advagtage effect
                        SpawnCloakingEffect((Ship *)spaceobj, etgSpecialPurposeEffectTable[EGT_CLOAK_OFF]);

                        ((Ship *) (spaceobj))->shipDeCloakTime = universe.totaltimeelapsed;
                    }
                }
                bitClear(spaceobj->flags,SOF_Cloaking);
                bitSet(spaceobj->flags,SOF_DeCloaking);
            }       //potential problem..ship flys into field..flys out..
                    //starts to decloak...flys back in, ship will decloak
                    //fully before recloaking...don't worry about since
                    //cloak times too fast too care
        }

        if(spaceobj->objtype == OBJ_ShipType)
        {
            if( ((Ship *)spaceobj)->shiptype == SalCapCorvette)
            {
                if(((SalCapCorvetteSpec *)((Ship *)spaceobj)->ShipSpecifics)->tractorBeam)
                {
                    //attached so decloak
                    if(bitTest(spaceobj->flags,SOF_Cloaked))
                    {
                        bitClear(spaceobj->flags,SOF_Cloaked);
                        if(spaceobj->objtype == OBJ_ShipType)
                        {
                            //if object was a ship set objects decloaking time for cloak advagtage effect
                            SpawnCloakingEffect((Ship *)spaceobj, etgSpecialPurposeEffectTable[EGT_CLOAK_OFF]);

                            ((Ship *) (spaceobj))->shipDeCloakTime = universe.totaltimeelapsed;
                        }
                    }
                    bitClear(spaceobj->flags,SOF_Cloaking);
                    bitSet(spaceobj->flags,SOF_DeCloaking);
                }
            }
        }

        //Case 1, object is cloaking
        if(bitTest(spaceobj->flags,SOF_Cloaking))
        {
            //object is cloaking..so keep cloaking it
/***** calculated the inverse of CloakingTime in CloakGeneratorStaticInit and multiply instead of divide *****/
            cloakstruct->CloakStatus += universe.phystimeelapsed*cloakgeneratorstatics->CloakingTime;
            if(cloakstruct->CloakStatus >= 1.0f)
            {
                //object is now cloaked...so stop cloaking it and make it fully 'cloaked'
                cloakstruct->CloakStatus = 1.0f;          //set for assurance
                bitSet(spaceobj->flags,SOF_Cloaked);      //make cloaked
                bitClear(spaceobj->flags,SOF_Cloaking);   //stop from cloaking
                if(spaceobj->objtype == OBJ_ShipType)
                {
                    shipHasJustCloaked((Ship *)spaceobj);
                    SpawnCloakingEffect((Ship *)spaceobj, etgSpecialPurposeEffectTable[EGT_CLOAK_ON]);
                    //RemoveShipFromBeingTargeted(&universe.mainCommandLayer,(Ship *)spaceobj,FALSE);
                }
                else if(spaceobj->objtype == OBJ_AsteroidType)
                {
                    //need to remove the asteroid from resource collectors
                    dbgMessagef("\nMake Bryce remove asteroids from game info since you just cloaked one.");
                }
            }
        }
        else if(bitTest(spaceobj->flags,SOF_DeCloaking))
        {
            //object is decloaking, so keep decloaking it
/***** calculated the inverse of DeCloakingTime in CloakGeneratorStaticInit and multiply instead of divide *****/
            cloakstruct->CloakStatus -= universe.phystimeelapsed*cloakgeneratorstatics->DeCloakingTime;
            if(cloakstruct->CloakStatus <= 0.0f)
            {
                //Object is now fully decloaked so stop decloaking it and remove it from the list
                cloaknode=cloaknode->next;                  //we're about to delete this node so move to next
                CloakGeneratorRemoveShipReferences(ship,(Ship *)spaceobj);  //delete everything about it
                continue;       //we now continue the loop rather than letting the other code continue :)
            }
        }
        cloaknode = cloaknode->next;
    }
}
void MineLayerAttackRun(Ship *ship,SpaceObjRotImpTarg *target,AttackSideStep *attacksidestep,AttackSideStepParameters *parameters)
{
    vector trajectory;
    //real32 dist;
    real32 range;
    //real32 temp;
//    bool didshoot;
    ShipStaticInfo *shipstaticinfo = (ShipStaticInfo *)ship->staticinfo;
    Gun *gun;
    udword numGuns,target_class;
    GunInfo *guninfo = ship->gunInfo;
    //vector tmpvec;
    //real32 randegf;
    //sdword randeg;
    //matrix tmpmat;
    //vector targetheading;
    MinelayerCorvetteSpec *spec = (MinelayerCorvetteSpec *)ship->ShipSpecifics;
    MinelayerCorvetteStatics *minelayercorvettestatics;
    minelayercorvettestatics = (MinelayerCorvetteStatics *) ((ShipStaticInfo *)(ship->staticinfo))->custstatinfo;

    numGuns = guninfo->numGuns;

    gun = &guninfo->guns[0];
    if(target != NULL)
    {
        if(target->objtype == OBJ_ShipType)
            target_class = ((Ship *)target)->staticinfo->shipclass;
        else
            target_class = CLASS_NonCombat;
    }

    switch (ship->aistateattack)
    {
        case ATTACK_INIT:
        case APPROACH:
#ifdef DEBUG_ATTACK
            dbgMessagef("\nShip %x MINELAYER_ATTACK_APPROACH",(udword)ship);
#endif
            aishipGetTrajectory(ship,target,&trajectory);
            aishipFlyToShipAvoidingObjs(ship,target,AISHIP_PointInDirectionFlying,0.0f);
            range = RangeToTarget(ship,target,&trajectory);

			//lets check if we want to force drop...
			if(target->objtype == OBJ_ShipType)
			{
				if(((Ship *)target)->shiptype == Mothership)
				{
					//its a mothership
					vector tempvec;
					real32 tempreal;
					vecSub(tempvec,target->collInfo.collPosition,ship->collInfo.collPosition);
					tempreal = vecMagnitudeSquared(tempvec);
					if(tempreal < mothershipDistSqr)
					{
						//we're within range of force dropping!
						ship->aistateattack = DROP_MOTHERSHIP;
					}
					break;
				}

			}


            if (range < minelayercorvettestatics->breakInAwayDist)
            {
                ship->aistateattack = BREAKPOSITION;
                spec->aivec.x = 0.0f;
                spec->aivec.y = 0.0f;
                spec->aivec.z = 0.0f;
            }

            break;
		case DROP_MOTHERSHIP:
			{
				vector tempvec;
				real32 tempreal;
				vecSub(tempvec,ship->collInfo.collPosition,target->collInfo.collPosition);
				tempreal = vecMagnitudeSquared(tempvec);
				vecNormalize(&tempvec);
				if(tempreal > mothershipDistSqr2)
				{
					ship->aistateattack = ATTACK_INIT;
				}
				if(aitrackHeadingWithFlags(ship,&tempvec,0.97f,AITRACKHEADING_IGNOREUPVEC))
				{
					if(MinelayerCorvetteStaticMineDrop(ship,target))		//problem...there will be other targets...bah..lets see..
					{
						MinelayerCorvetteOrderChangedCleanUp(ship);
					}
				}
				break;
			}
        case BREAKPOSITION:
#ifdef DEBUG_ATTACK
        dbgMessagef("\nShip %x BREAKPOSITION",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);
            vecNormalize(&trajectory);

            SetAIVecHeading(ship,target,&trajectory);

            ship->aistateattack = BREAK1;

        case BREAK1:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x BREAK1",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);


            //aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            aishipFlyToPointAvoidingObjs(ship,&target->posinfo.position,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            if(range < minelayercorvettestatics->DropRange)
            {
                //temp
                vecNormalize(&trajectory);
                SetAIVecHeading(ship,target,&trajectory);
                //temp

                ship->aistateattack = KILL;    //within mining range so start dropping
                spec->aispheretime=0.0f;            //reset time;
            }

            break;
        case KILL:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x KILL",(udword)ship);
#endif
            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);

            spec->aispheretime += universe.phystimeelapsed;

            if(gunCanShoot(ship, gun))
            {
                if(gun->numMissiles > 0)
                {
                   spec->mineaistate = MINE_DROP_ATTACK;
                   MinelayerCorvetteFire(ship,target);
                 }
            }
            if(range > minelayercorvettestatics->DropStopRange)
            {   //out of range....
                ship->aistateattack = BREAK2;
            }
            if(spec->aispheretime > minelayercorvettestatics->Break2SphereizeFreq)
            {    //time to sphereize;
                spec->aivec.x =0.0f;
                spec->aivec.y =0.0f;
                spec->aivec.z =0.0f;
                spec->aispheretime = -1000000.0f;     // Reset, and never do again till next attack pass...
                vecNormalize(&trajectory);
                SetAIVecHeading(ship,target,&trajectory);

#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x KILL: Adjust for Break2 Sphereizing Godliness Maneuver :)",(udword)ship);
#endif

            }

            aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            break;
        case BREAK2:
#ifdef DEBUG_ATTACK
    dbgMessagef("\nShip %x BREAK2",(udword)ship);
#endif

            aishipGetTrajectory(ship,target,&trajectory);
            range = RangeToTarget(ship,target,&trajectory);
            aishipFlyToPointAvoidingObjs(ship,&spec->aivec,AISHIP_FastAsPossible | AISHIP_PointInDirectionFlying,INTERCEPTORBREAK_MINVELOCITY);
            if(range > minelayercorvettestatics->FlyAwayDist[target_class] ||
               (MoveReachedDestinationVariable(ship,&spec->aivec,minelayercorvettestatics->FlyAwayTolerance)))
            {    //turn around and start over
                ship->aistateattack = APPROACH;
            }
            break;
        default:
            dbgAssert(FALSE);
            break;
    }

}
void univUpdateMineWallFormations()
{
    Node *node,*minenode,*tempnode;
    //Missile *mine, *mineend = NULL, *minestart, *mineendtemp;
    MineFormationInfo *mineformationinfo;
    Missile *minestart;
    vector tempvec;
    node = universe.MineFormationList.head;
    while(node != NULL)
    {
        mineformationinfo = (MineFormationInfo *) listGetStructOfNode(node);

        if(mineformationinfo->MineList.num == 9)             //use another number other than 0 later..maybe 8? Tunable
        {
            //no more mines in formation so destroy this here formation

            //destroy any effects that are still going

            //here re-task mines (make not Force Dropped...)
            if(mineformationinfo->FULL)
            {
                //no more mines are going to be added...

                minenode = mineformationinfo->MineList.head;
                //set formationinfo to NULL
                while(minenode != NULL)
                {
                    minestart = (Missile *) listGetStructOfNode(minenode);

                    minestart->formationinfo = NULL;
                    minenode = minenode->next;
                }
                listRemoveAll(&mineformationinfo->MineList);    //removes all mine links
                tempnode = node->next;
                listDeleteNode(node);       //destroys mineformation
                node = tempnode;
                continue;
            }
        }
        else
        {
            //mines exist in formation
            if(mineformationinfo->FULL)
            {

                minenode = mineformationinfo->MineList.head;

                while(minenode != NULL)
                {
                    minestart = (Missile *) listGetStructOfNode(minenode);

                    vecSub(tempvec, minestart->posinfo.position, minestart->formation_position);
                    if(vecMagnitudeSquared(tempvec) > MINE_GONE_TOO_FAR_SQR)
                    {
                        tempnode = minenode->next;
                        minestart->formationinfo = NULL;
                        listRemoveNode(&minestart->formationLink);
                        minenode = tempnode;
                        continue;
                    }
                    minenode = minenode->next;
                }
            }
        }
ret:
        node = node->next;
    }

}
Example #18
0
/*-----------------------------------------------------------------------------
    Name        : pingListDraw
    Description : Draw all pings from farthest to nearest.
    Inputs      : camera - the camera we're rendering from
                  modelView, projection - current matrices
                  viewPort - rectangle we're rending in, for the TO legend
    Outputs     :
    Return      :
    Note        : The renderer should be in 2D mode at this point.
----------------------------------------------------------------------------*/
void pingListDraw(Camera *camera, hmatrix *modelView, hmatrix *projection, rectangle *viewPort)
{
    real32 pingAge, pingCycle, pingMod, pingSize;
    real32 x, y, radius;
    Node *thisNode, *nextNode;
    ping *thisPing;
    vector distSquared;
    sdword nSegments, index, rowHeight, xScreen, yScreen;
    oval o;
    udword TOFlags = 0;
    fonthandle fhSave;
    toicon *icon;
    color col;
    real32 realMargin;
    ShipClass shipClass;
    static real32 lastProximityPing = REALlyBig;
    static real32 lastAnomolyPing = REALlyBig;
    static real32 lastBattlePing = REALlyBig;
    static real32 lastHyperspacePing = REALlyBig;
    static real32 lastNewshipPing = REALlyBig;
    bool pingset;

    //start by sorting the ping list from farthest to nearest
    thisNode = pingList.head;

    while (thisNode != NULL)
    {                                                       //scan all pings
        nextNode = thisNode->next;
        thisPing = listGetStructOfNode(thisNode);

        if (thisPing->owner != NULL)
        {
            thisPing->centre = thisPing->owner->posinfo.position;
        }
        vecSub(distSquared, camera->eyeposition, thisPing->centre);
        thisPing->cameraDistanceSquared = vecMagnitudeSquared(distSquared);
        TOFlags |= thisPing->TOMask;

        thisNode = nextNode;
    }
    listMergeSortGeneral(&pingList, pingListSortCallback);

    //now the list is sorted; proceed to draw all the pings
    thisNode = pingList.head;

    pingset = FALSE;

    while (thisNode != NULL)
    {                                                       //scan all pings
        nextNode = thisNode->next;
        thisPing = listGetStructOfNode(thisNode);

        pingCycle = thisPing->pingDuration + thisPing->interPingPause;
        pingAge = universe.totaltimeelapsed - thisPing->creationTime;
        pingMod = (real32)fmod((double)pingAge, (double)pingCycle);
        if (pingMod <= thisPing->pingDuration)
        {
            pingSize = (thisPing->size - thisPing->minSize) * pingMod / thisPing->pingDuration + thisPing->minSize;
            selCircleComputeGeneral(modelView, projection, &thisPing->centre, max(thisPing->size,thisPing->minSize), &x, &y, &radius);
            if (radius > 0.0f)
            {
                radius = max(radius, thisPing->minScreenSize);
                radius *= pingSize / max(thisPing->size,thisPing->minSize);
                o.centreX = primGLToScreenX(x);
                o.centreY = primGLToScreenY(y);
                o.radiusX = o.radiusY = primGLToScreenScaleX(radius);
                nSegments = pieCircleSegmentsCompute(radius);
                primOvalArcOutline2(&o, 0.0f, 2*PI, 1, nSegments, thisPing->c);

                /* starting to draw a new ping so play the sound */
                if (!smZoomingIn && !smZoomingOut && !pingset)
                {
                    switch (thisPing->TOMask)
                    {
                        case PTOM_Anomaly:
                            if (pingSize <=lastAnomolyPing)
                            {
                                soundEvent(NULL, UI_SensorsPing);
                                pingset = TRUE;
                                lastAnomolyPing = pingSize;
                            }
                            break;
                        case PTOM_Battle:
                            if (pingSize <= lastBattlePing)
                            {
                                soundEvent(NULL, UI_PingBattle);
                                pingset = TRUE;
                                lastBattlePing = pingSize;
                            }
                            break;
                        case PTOM_Hyperspace:
                            if (pingSize <=  lastHyperspacePing)
                            {
                                soundEvent(NULL, UI_PingHyperspace);
                                pingset = TRUE;
                                lastHyperspacePing = pingSize;
                            }
                            break;
                        case PTOM_Proximity:
                            if (pingSize <= lastProximityPing)
                            {
                                soundEvent(NULL, UI_PingProximity);
                                pingset = TRUE;
                                lastProximityPing = pingSize;
                            }
                            break;
                        case PTOM_NewShips:
                            if (pingSize <= lastNewshipPing)
                            {
                                soundEvent(NULL, UI_PingNewShips);
                                pingset = TRUE;
                                lastNewshipPing = pingSize;
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        thisNode = nextNode;
    }

    //draw the blip TO
    if (smTacticalOverlay)
    {
        realMargin = primScreenToGLScaleX(viewPort->x0);
        fhSave = fontCurrentGet();                          //save the current font
        fontMakeCurrent(selGroupFont2);                     // use a common, fairly small font
        rowHeight = fontHeight("M");                        // used to space the legend
        yScreen = viewPort->y0 + rowHeight;                 //leave some space at the top to start
        radius = primScreenToGLScaleX(rowHeight)/2;
        xScreen = viewPort->x0 + (sdword)(rowHeight * 2.5);

        for (index = 0; index < PTO_NumberTOs; index++)
        {
            if ((TOFlags & pingTOList[index].bitMask))
            {
    //            fontPrint(xScreen, yScreen, *pingTOList[index].c, "O");
                pingTOList[index].lastTimeDrawn = universe.totaltimeelapsed;
            }
            if (universe.totaltimeelapsed - pingTOList[index].lastTimeDrawn <= pingTOLingerTime)
            {
                o.centreX = viewPort->x0 + rowHeight * 3 / 2;
                o.centreY = yScreen + rowHeight / 2;
                o.radiusX = o.radiusY = rowHeight / 2;
                primOvalArcOutline2(&o, 0.0f, TWOPI, 1, pingTONSegments, *pingTOList[index].c);
                fontPrint(xScreen, yScreen, TO_TextColor, strGetString(pingTOList[index].stringEnum));
                yScreen += rowHeight + 1;
            }
        }
        for (shipClass = 0; shipClass < NUM_CLASSES; shipClass++)
        {
            if (!toClassUsed[shipClass][0])
            {
                continue;
            }
            icon = toClassIcon[shipClass];
            fontPrint(xScreen, yScreen + (rowHeight>>2), TO_TextColor, ShipClassToNiceStr(shipClass));
#if TO_STANDARD_COLORS
            col = teFriendlyColor;
#else
            col = teColorSchemes[universe.curPlayerIndex].tacticalColor;
#endif
            col = colRGB(colRed(col)/TO_IconColorFade, colGreen(col)/TO_IconColorFade, colBlue(col)/TO_IconColorFade);
            primLineLoopStart2(1, col);

            for (index = icon->nPoints - 1; index >= 0; index--)
            {
               primLineLoopPoint3F(realMargin + primScreenToGLX(rowHeight*1.5) + icon->loc[index].x * radius,
                                          primScreenToGLY(yScreen + rowHeight/2) + icon->loc[index].y * radius);
            }
            primLineLoopEnd2();
            yScreen += rowHeight + 1;
        }

        fontMakeCurrent(fhSave);
    }
}