void HeraldExterminator::calculate_fire_special() { special_low = FALSE; if(fire_special) { if((batt < special_drain) && (!cloak)) { special_low = TRUE; return; } if(special_recharge != 0) return; if(cloak) { cloak = FALSE; play_sound2(data->sampleSpecial[1]); } else { cloak = TRUE; play_sound2(data->sampleSpecial[0]); batt -= special_drain; } special_recharge = special_rate; } }
void NaroolLurker::calculate_fire_special() { STACKTRACE; special_low = FALSE; if (fire_special) { if ((batt < special_drain) && (!cloak)) { special_low = TRUE; return; } if (special_recharge > 0) return; if (cloak) { cloak = FALSE; play_sound2(data->sampleSpecial[1]); recharge_amount = normalRechargeAmount; } else { cloak = TRUE; play_sound2(data->sampleSpecial[0]); //batt -= special_drain; //recharge_amount = 1; recharge_amount = 0; } special_recharge = special_rate; } }
void trapShip::calculate() { STACKTRACE; if (!(ship && ship->exists())) { ship = 0; // you've to do it yourself cause you return before the other calculate call !! state = 0; return; } if (ship->batt > 0) { pos = ship->normal_pos(); ship->nextkeys &= ~(keyflag::left | keyflag::right | keyflag::special | keyflag::thrust | keyflag::back | keyflag::fire | keyflag::altfire); // must be unconditional, outside the loop (otherwise virtually 1 extra loop/waittime is added) ++drainRate; if (drainRate >= drainDelay) { ship->batt -= drainAmount; //drainRate = 0; drainRate -= drainDelay; } } else { state = 0; return; } if (soundDelay < 25) // Needed to make sound loop properly :) soundDelay++; else { play_sound2(data->sampleExtra[1]); soundDelay = 0; } SpaceObject::calculate(); }
void TeronBuilder::calculate_fire_special() { STACKTRACE; special_low = FALSE; if ( fire_special && (fire_weapon || turn_left || turn_right) ) { if ( special_recharge > 0 ) return; if ( fire_weapon ) { if ( !activate_special() ) return; message.out( "> Activated Command:" ); } else if ( turn_right ) { if ( current_option < TERON_BUILDER_OPTIONS-1 ) current_option++; else current_option = 0; } else if ( turn_left ) { if ( current_option > 0 ) current_option--; else current_option = TERON_BUILDER_OPTIONS-1; } message.out( option[current_option].phrase ); special_recharge += special_rate; play_sound2(data->sampleSpecial[special_sample]); } }
void DaktaklakpakMine::calculate() { AnimatedShot::calculate(); if (!mineactive) { mineArming -= frame_time; if (mineArming <= 0) { mineactive = TRUE; v = 0; vel = 0; } } else { SpaceObject *o, *t = NULL; double oldrange = 999999; Query a; for (a.begin(this, bit(LAYER_SHIPS),(missileRange *.9)); a.current; a.next()) { o = a.currento; if (!o->sameTeam(this) && (distance(o) < oldrange) && !(o->isAsteroid() || o->isPlanet())) { t = o; oldrange = distance(o); } } if (t) { add(new Missile(this,0,(trajectory_angle(t)), missileVelocity,missileDamage,missileRange,missileArmour, this,data->spriteExtra)); play_sound2(data->sampleExtra[0]); destroy(); } } }
void DaktaklakpakVivisector::inflict_damage(SpaceObject *other) { if (drillFrames > 0) if (!latched) if ((!(sameTeam(other))) && (other->isShip())) { latched=TRUE; grabbed= (Ship *) other; grabangle= (trajectory_angle(other) ); grabdistance = (distance(other) * 1.1); grabshipangle = (other->get_angle()); drillDamageLeft = weaponDamage; play_sound2(data->sampleExtra[1]); if ((drillFrames / frame_time)< weaponDamage) { drillDamagePerDamageFrame = (weaponDamage/drillFrames) + ((weaponDamage % drillFrames) > 0.00001); damageFrameLeft = 1; damageFrameAmount = 1; } else { damageFrameAmount = (drillFrames/weaponDamage); damageFrameLeft = damageFrameAmount; drillDamagePerDamageFrame = 1; } } Ship::inflict_damage(other); }
void MonoMissile::calculate() { STACKTRACE; Missile::calculate(); if ( target != last_target ) set_up_beacons(); last_target = target; if ( !(target && target->exists()) || target->isInvisible() ) { target = NULL; return; } if ( distance( from_beacon ) > distance( to_beacon )) { play_sound2( data->sampleWeapon[1] ); if ( from_beacon ) delete from_beacon; from_beacon = new SpaceLocation( this, pos, 0.0 ); double tangle = trajectory_angle( target ); int itangle = (int)((tangle + PI/4) / (PI/2)) % 4; changeDirection( (PI/2) * itangle ); sprite_index = itangle; if ( itangle % 2 == 0 ) { if ( to_beacon ) delete to_beacon; to_beacon = new SpaceLocation( this, Vector2(2*target->normal_pos().x-pos.x, pos.y), 0.0 ); } else if ( itangle % 2 == 1 ) { if ( to_beacon ) delete to_beacon; to_beacon = new SpaceLocation( this, Vector2(pos.x, 2*target->normal_pos().y-pos.y), 0.0 ); } } }
void LassoLaser::collide(SpaceObject *o) { double old_length = length; double old_oldlen; int collison = FALSE; if((!canCollide(o)) || (!o->canCollide(this))) return; for (int i=0; i < BCC ; i++) { old_oldlen = o->collide_ray(Vector2(oldnx[i], oldny[i]), Vector2(oldnx[i] + oldex[i], oldny[i] + oldey[i]), oldlen[i]); collison = (collison || (old_oldlen != oldlen[i])); } length = o->collide_ray(normal_pos(), normal_pos() + edge(), length); if ( (length == old_length) && (!collison) ) return; play_sound2(LeftMissile->data->sampleExtra[0]); if ((LeftMissile->exists()) && (LeftMissile->sameShip(this)) && (!snapped)) LeftMissile->changeDirection(normalize(LeftMissile->get_angle()+PI/2,PI2)); if ((RightMissile->exists()) && (RightMissile->sameShip(this)) && (!snapped)) RightMissile->changeDirection(normalize(RightMissile->get_angle()-PI/2,PI2)); state = 0; snapped = TRUE; }
int ArilouTrapper::activate_weapon() { STACKTRACE; if (cloak) { play_sound2(data->sampleSpecial[0]); cloak = FALSE; play_sound2(data->sampleWeapon[1]); add(new quasiTrap(Vector2(0.0, (size.y * 1)), angle, trapInitialVelocity, trapAccel, weaponRange*1.5, drainDelay, drainAmount, trapTurn, this, data->spriteWeaponExplosion)); } else { play_sound2(data->sampleWeapon[0]); add(new AnimatedShot(this, Vector2(0.0, (size.y/3.0)), angle , weaponVelocity, weaponDamage, weaponRange, weaponArmour, this, data->spriteWeapon, 10, 12, 1.0)); } return(TRUE); }
void NaroolGas::soundExplosion() { STACKTRACE; if (!hitShip) { play_sound2(data->sampleExtra[1]); } return; }
void BasiliskGas::soundExplosion() { STACKTRACE; if (!hitShip) { play_sound2(data->sampleExtra[3]); } return; }
void TeronBuilder::calculate_fire_weapon() { STACKTRACE; if ( fire_weapon && !fire_special && (thrust || turn_left || turn_right) ) { if ( weapon_recharge > 0 ) return; if ( thrust ) { if ( select_all ) { select_all = false; current_drone = NULL; message.out( "All drones deselected" ); } else { select_all = true; message.out( "All drones selected" ); } } else if ( turn_right ) { select_all = false; TeronDrone* first_drone = NULL; TeronDrone* next_drone = NULL; Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( !next_drone && sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { next_drone = (TeronDrone*)q.currento; if ( !first_drone ) first_drone = (TeronDrone*)q.currento; } if ( q.currento == current_drone ) { next_drone = NULL; } } q.end(); if ( next_drone ) current_drone = next_drone; else current_drone = first_drone; message.out( "Next drone selected" ); } else if ( turn_left ) { select_all = false; TeronDrone* prev_drone = NULL; Query q; for( q.begin( this, bit(LAYER_SHIPS), selectRange ); q.currento; q.next() ) { if ( q.currento == current_drone ) { if ( prev_drone ) break; } if ( sameShip( q.currento ) && q.currento->get_sprite() == data->TERON_DRONE_SPRITE ) { prev_drone = (TeronDrone*)q.currento; } } q.end(); current_drone = prev_drone; message.out( "Prev drone selected" ); } weapon_recharge += weapon_rate; play_sound2(data->sampleWeapon[weapon_sample]); } }
int ArilouTrapper::handle_damage(SpaceLocation *source, double normal, double direct) { STACKTRACE; if ( cloak == TRUE ) { normal = normal/2; direct = direct/2; } play_sound2(data->sampleExtra[0]); return Ship::handle_damage(source, normal, direct); }
int SefyNautilus2::activate_weapon() { STACKTRACE; if (!arm_movement) { arm_movement = true; play_sound2(data->sampleWeapon[0],256, iround(1000 * (data->sampleWeapon[0]->len / arm_period))); weapon_recharge += weapon_rate; } return FALSE; }
int AstromorphBasilisk::activate_weapon() { STACKTRACE; if (aimline == NULL) { add(aimline = new BasiliskAimline(this, angle, tw_color(0, 96, 0), tw_color(0, 240, 0), aimlineRange, this, Vector2(0, (get_size().y / 2.07)), aimlineAngleRange)); play_sound2(data->sampleWeapon[0]); } return(FALSE); }
bool BChain::regrow(int maxSegs) { STACKTRACE; int segCount = 0; Seg* cur = this; Seg* last = NULL; // increment down the list, looking for hurt sections while(cur != NULL && ((cur->health == max_health) && (segCount < maxSegs))) { last = cur; cur = cur->Next_Seg; segCount++; } if (cur != NULL && (cur->health < max_health)) { play_sound2(data->sampleExtra[1]); cur->health++; return true; } else if (cur == NULL && last != NULL && segCount < maxSegs) { Vector2 dd = - Seg_Distance * unit_vector(last->angle); Vector2 ppos = dd + last->pos; //Create a new Seg that knows that it's attached to Cur_Seg last->Next_Seg = new BasiLink(ship,ppos,last->angle, sprite, last, NULL, mass, 1, max_health, max_hurt_flash_time, hurt_damage, friction); //Add it to the game add(last->Next_Seg); ((AstromorphBasilisk*)ship)->numSegs++; play_sound2(data->sampleExtra[1]); return true; } return false; }
void NaroolGas::inflict_damage(SpaceObject *other) { STACKTRACE; play_sound2(data->sampleExtra[1]); if (other->isShip()) { add( new NaroolPoison(this, duration, poison, (Ship*)other, data->spriteWeapon)); add(new FixedAnimation(this, other, data->spriteWeaponExplosion, 0, 8, 150, LAYER_EXPLOSIONS)); } else { add(new Animation(this, pos, data->spriteWeaponExplosion, 0, 8, 150, LAYER_EXPLOSIONS)); } AnimatedShot::inflict_damage(other); return; }
int WissumTripod::activate_special() { STACKTRACE; // this is handled implicitly in activate_weapon, this must return true // so that fire_special is set; this must consume very little fuel, // for "normal use". if ( Nactive < 3 ) { fire_guns(2); if (weapon_sample >= 0) play_sound2(data->sampleWeapon[weapon_sample]); return TRUE; // ok, the special was used } // a special case for the special is, when all 3 thrusters have been // activated, do something like the hotspot special. This consumes // extra fuel. if ( Nactive == 3 && batt >= specialDrainFuelDump ) { int i; for ( i = 0; i < 3; ++i ) { double a; a = angle; angle = moveangles[i]; game->add( new FuelDump(this, Vector2(0,-25), angle+PI, specialVelocity, specialDamage, specialRange, specialArmour, this, this->data->spriteExtra, 1.0, 0) ); angle = a; } // extra fuel (note that special_drain is also subtracted, later on): batt -= specialDrainFuelDump - special_drain; if ( batt < 0 ) batt = 0; play_sound(data->sampleExtra[0]); return TRUE; // ok, the 3 things were launched } return FALSE; }
void ArilouTrapper::calculate_fire_special() { STACKTRACE; special_low = FALSE; if (fire_special) { if ((batt < special_drain) && (!cloak)) { special_low = TRUE; return; } if (special_recharge > 0) return; if (cloak) { play_sound2(data->sampleSpecial[0]); cloak = FALSE; recharge_amount = normalRechargeAmount; } else { play_sound2(data->sampleSpecial[0]); cloak = TRUE; batt -= special_drain; recharge_amount = 1; } special_recharge = special_rate; } }
void DruugeMauler::calculate_fire_special() { STACKTRACE; if ((fire_special) && (crew > 1) && (batt < batt_max) && (special_recharge <= 0)) { batt += special_drain; if (batt > batt_max) batt = batt_max; crew--; special_recharge = special_rate; play_sound2(data->sampleSpecial[0]); } }
void HarikaYornRavager::calculate() { if (regenrating) { if (crew < crew_max) { if ((regenrateCount -= frame_time) < 0) { crew++; play_sound2(data->sampleExtra[1]); regenrateCount = regenrateFrames; } } else regenrating = FALSE; } else if (!(regenrating) && (crew < crew_max)) { regenrating = TRUE; regenrateCount = regenrateFrames; } if(shieldFrames > 0) shieldFrames-= frame_time; Ship::calculate(); }
void UlzrakInterceptor::calculate() { STACKTRACE; double fracDone; if ((!zoomActive) && (!zoomSequenceInitiated)) spriteShift = 0; if (zoomActive) { mass = this->specialZoomMass; if (zoomReversed) this->zoomVel = (-1) * unit_vector(this->angle) * this->specialZoomSpeedAddition; else this->zoomVel = unit_vector(this->angle) * this->specialZoomSpeedAddition; if (this->specialZoomSpeedIsAdditive) set_vel ( this->normalVel + this->zoomVel ); else set_vel ( this->zoomVel ); this->damage_factor = this->specialCollisionDamage; this->zoomCounter += frame_time; this->DrawZoomLines(); spriteShift = 3; if (zoomCounter>=this->specialZoomTime) { UnZoom(); } } else if (zoomCounter >= this->specialActivationTime) { play_sound2((this->data->sampleSpecial[1])); this->zoomActive = true; this->zoomReversed = false; this->zoomSequenceInitiated = false; this->zoomCounter = 0; //storing away the normal Velocity this->normalVel = this->vel; this->zoomVel = unit_vector(this->angle) * this->specialZoomSpeedAddition; this->inflictDamageCounter = 0; } else if (zoomSequenceInitiated) { zoomCounter += frame_time; fracDone = (double)zoomCounter / (double)this->specialActivationTime; spriteShift = (int)((fracDone * 3.0) + 0.5); } sprite_index_override = get_index(this->angle) + 64 * spriteShift; sprite_index = sprite_index_override; Ship::calculate(); sprite_index = sprite_index_override; }
void DaktaklakpakVivisector::calculate() { Ship::calculate(); if(drillFrames > 0) { drillFrames-= frame_time; if ((drillFrames <= 0) && (!latched)) { play_sound2(data->sampleWeapon[0]); } } else latched = FALSE; if (grabbed != NULL) if (!(grabbed ->exists())){ latched = FALSE; grabbed = NULL; } if (latched) { damageFrameLeft-=frame_time; if (damageFrameLeft <=0) { damageFrameLeft += damageFrameAmount; if (drillDamageLeft < drillDamagePerDamageFrame) damage(grabbed, drillDamageLeft); else { damage(grabbed, drillDamagePerDamageFrame); drillDamageLeft -= drillDamagePerDamageFrame; } } grabangle = (grabbed->get_angle() - grabshipangle) + grabangle; angle=grabangle; grabshipangle = grabbed->get_angle(); nextkeys &= ~(keyflag::left | keyflag::right | keyflag::thrust); pos = grabbed->normal_pos()-((unit_vector(grabangle )) * grabdistance); } int j = 0; for (int i = 0; i < numMines; i += 1) { weaponObject[i-j] = weaponObject[i]; if (!weaponObject[i]->exists()) j += 1; if (j) weaponObject[i] = NULL; } numMines -= j; }
int KorvianSniper::activate_weapon() { // note that target=0 is only set after this routine is called in ship::calculate // so we need to check if it exists ... /*if (cloak && target && target->exists()) { if (distance(target) < weaponRange * 3) { angle = intercept_angle2(pos, vel * 1.0, weaponVelocity, target->normal_pos(), target->get_vel() ); } else angle = trajectory_angle(target); }*/ game->add(new SniperMissile( Vector2(0.0, size.y / 2.0), angle, weaponVelocity, weaponDamage, weaponRange, weaponArmour, this, data->spriteWeapon)); play_sound2(data->sampleWeapon[0]); /*game->add(new AnimatedShot(this, Vector2(0.0, size.y / 2.0), angle, weaponVelocity, weaponDamage, weaponRange, weaponArmour, this, data->spriteWeapon, 1, 12, 1.0));*/ return(TRUE); }
void KorvianSniper::calculate() { double angle2; if(beep == TRUE) { if(target && target->exists() && !target->isInvisible()) { angle2 = angle - intercept_angle2(pos, vel * 1.0, weaponVelocity, target->normal_pos(), target->get_vel() ); Vector2 v = 350*Vector2(unit_vector(angle+PI/2)); double w = v.dot(target->get_vel())/distance(target); if(w < 0.0) w = -w; if(w > angle2 && angle2 > -w) { play_sound2(data->sampleSpecial[0]); beep = FALSE; } } } Ship::calculate(); }
trapShip::trapShip(SpaceLocation *creator, Ship *oship, int drainDelayRate, int drainAmountof, SpaceSprite *osprite, int ofcount, int ofsize) : SpaceObject(creator, oship->normal_pos(), 0.0, osprite), ship(oship) { STACKTRACE; play_sound2(data->sampleExtra[1]); collide_flag_anyone = 0; drainRate = 0; drainDelay = drainDelayRate; drainAmount = drainAmountof; soundDelay = 0; // limiting case, where the enemy recharges faster than the weapon drains. while (drainAmount * ship->recharge_rate < ship->recharge_amount * drainDelay*frame_time) { drainDelay -= 1; if (drainDelay < 1) { drainDelay = 1; break; } } }
void KorvianSniper::calculate_fire_special() { if(fire_special) { special_low = FALSE; beep = TRUE; } if(fire_special) { if((batt < special_drain)) { special_low = TRUE; return; } if(abs(get_vel()) > 0.00001) { play_sound2(data->sampleSpecial[1]); change_vel(-get_vel()); //if(special_recharge > 0) //return; batt -= special_drain; } special_recharge = special_rate; } }
int BasiLink::handle_damage(SpaceLocation *source, double normal, double direct) { STACKTRACE; int totalDamage = int( normal+direct + 0.5); if (totalDamage == 0) return 0; //If there are no Segs, the Seg is destroyed. if (!Prev_Seg && !Next_Seg) { state=0; return totalDamage; } if (hurty_time > 0) return 0; //If a next Seg exists, the damage is passed to it. //directDamage is used so that we don't play the damage sound //again. if (Next_Seg) return damage(Next_Seg, 0, totalDamage); else { if (totalDamage > health) { Prev_Seg->Next_Seg=NULL; damage(Prev_Seg, 0, totalDamage - health); play_sound2(data->sampleExtra[0]); die(); ((AstromorphBasilisk*)ship)->numSegs--; } else health -= totalDamage; } return 1; }
void SefyNautilus2::calculate() { STACKTRACE; ManageParts->oldpos = pos; ManageParts->oldvel = vel; Ship::calculate(); // this can apply extra changes to this ship pos,vel ! ManageParts->calculate_manager(); if ( arm_movement ) { if (fire_weapon && batt > 0 ) { if (arm_time <= arm_period) { arm_time += frame_time * 1E-3; arm_time_last = arm_angle; arm_angle = (0.5 - 0.5*cos(arm_time * PI / arm_period)) * arm_maxangle; // update the arms: if (arm_angle <= arm_maxangle) { // anti-cl.w. ArmLeft->offset_angle = -arm_angle; // clockwise ArmRight->offset_angle = arm_angle; } } if (weapon_recharge <= 0) { weapon_recharge += weapon_rate; batt -= weapon_drain; } if (weapon_recharge > 0) weapon_recharge -= frame_time; } // unleash the fury!! else if (arm_time > 0) { if (arm_time_last < arm_period2) arm_time_last = arm_time_last; double temp; temp = (arm_time_last / arm_maxangle) * arm_maxdamage; if (temp < arm_mindamage) temp = arm_mindamage; play_sound2(data->sampleWeapon[0],5); if (sound_recharge <= 0) { play_sound2(data->sampleWeapon[1]); sound_recharge += arm_period2 / arm_period; ArmLeft->damage_factor = temp; ArmRight->damage_factor = temp; } if (sound_recharge > 0) sound_recharge -= frame_time * 1E-3; //ArmLeft->collide_flag_anyone = ALL_LAYERS; //ArmRight->collide_flag_anyone = ALL_LAYERS; //if (arm_angle <= 0.05) { // message.out("Bob!"); } arm_time -= frame_time * 1E-3; arm_angle = (0.5 - 0.5*cos(arm_time * PI / arm_period2)) * arm_maxangle; ArmLeft->offset_angle = -arm_angle; ArmRight->offset_angle = arm_angle; } else { arm_movement = false; // anti-cl.w. ArmLeft->offset_angle = 0; // clockwise ArmRight->offset_angle = 0; ArmLeft->damage_factor = 0; ArmRight->damage_factor = 0; //ArmLeft->collide_flag_anyone = ArmLeft->mother->collide_flag_anyone; //ArmRight->collide_flag_anyone = ArmRight->mother->collide_flag_anyone; } } // release the hook: /* if ( (this->nextkeys & keyflag::special) && (this->nextkeys & keyflag::fire ) ) if ( hook && hook->exists() ) hook->state = 0; */ // detect when the hook disappears - reset the pointer to 0 in that case if ( !(hook && hook->exists()) ) hook = 0; }
void AstromorphBasilisk::calculate() { STACKTRACE; // firing the weapon // vel*=0.99; if (aimline && !fire_weapon && batt - weapon_drain >= 0 && weapon_recharge <= 0) { play_sound2(data->sampleWeapon[1]); batt -= weapon_drain; if (recharge_amount > 1) recharge_step = recharge_rate; weapon_recharge += weapon_rate; regrow_delay = regrowTime; double a; if (aimline->target != NULL) { SpaceObject* targ = aimline->target; a = intercept_angle2(pos, vel * game->shot_relativity, weaponVelocity*aimBonus, targ->normal_pos(), targ->get_vel()); } else a = angle; add(new BasiliskGas(0.0, 0.0, a, (aimline->target != NULL) ? weaponVelocity*aimBonus : weaponVelocity, weaponDamage, weaponLife, weaponRange, iround(weaponArmour), poison, this, data->spriteWeapon, 1.0)); aimline->target = NULL; aimline = NULL; } // slithering //if (!(turn_left || turn_right || !thrust)) { //double frac = float(numSegs)/float(specialSegs); //double frac2 = numSegs/specialSegs; //double frac2 = magnitude(this->vel)/speed_max; double frac2 = 1.0; Vector2 normal; normal = Vector2(-vel.y, vel.x); normalize(normal); slitherFrame += frame_time * 1E-3; double a; //a = sin(PI * (frac2)*slitherFrame / 1.0 + (PI/2) ) *( (frac)*slitherAmount); // needs some work! a = (slitherAmount)*sin(slitherFrame * (frac2*slitherTime)/(PI/2) ); vel += (accel_rate*frame_time) * a * normal; /* slitherFrame -= frame_time; slitherTick += frame_time * slitherAmount; frac2 = sin(slitherTick); slitherFrame *= frac;*/ //if (slitherFrame < 0) //{ // slitherFrame = slitherTime; // bOtherWay = !bOtherWay; //} //angle -= (bOtherWay) ? (PI2/64) : -(PI2/64); /*accelerate(this, //normalize(angle - ((bOtherWay) ? (PI/4) : -(PI/4)), PI2), normalize(angle - (frac2*(PI/4))), slitherAccel*frac*frame_time, speed_max);*/ } // else { //slitherFrame = slitherTime/2; //bOtherWay = turn_right; } Ship::calculate(); // ouchification tickdown if (hurty_time <= 0) vel *= 1 - slitherFriction * frame_time; if (hurty_time >= 0) hurty_time -= frame_time * 1E-3; if (hurty_time < 0) hurty_time = 0; // regrowth if (batt == batt_max && regrowTime > 0) { regrow_delay -= frame_time * 1E-3; if (regrow_delay <= 0) if (Head) if (Head->regrow(specialSegs)) { batt -= regrowDrain; regrow_delay = regrowTime; } } }