@ -57,12 +57,6 @@ fromUTF8(
# endif // win32
# endif // ASSERT_DO_POPUP_AND_CRASH
enum
{
PLAYERS = 1 < < 0 ,
BOXES = 1 < < 1 ,
} ;
FILE * log_file = NULL ;
void quit_with_popup ( const char * message_utf8 , const char * title_utf8 )
@ -294,9 +288,9 @@ typedef struct QueryResult
cpVect pointA ;
cpVect pointB ;
} QueryResult ;
static THREADLOCAL char query_result_data [ 128 * sizeof ( QueryResult ) ] = { 0 } ;
static THREADLOCAL char query_result_data [ QUEUE_SIZE_FOR_ELEMENTS ( sizeof ( QueryResult ) , 128 ) ] = { 0 } ;
// the data starts off NULL, on the first call sets it to result data
static THREADLOCAL Queue query_result = { . data_length = 128 * sizeof ( QueryResult ) , . element_size = sizeof ( cpShape * ) } ;
static THREADLOCAL Queue query_result = { 0 } ;
static void shape_query_callback ( cpShape * shape , cpContactPointSet * points , void * data )
{
@ -315,7 +309,7 @@ static void shape_query_callback(cpShape *shape, cpContactPointSet *points, void
// shapes are pushed to query result
static void shape_query ( cpSpace * space , cpShape * shape )
{
query_result . data = query_result_data ;
queue_init ( & query_result , sizeof ( QueryResult ) , query_result_data , ARRLEN ( query_result_data ) ) ;
queue_clear ( & query_result ) ;
cpSpaceShapeQuery ( space , shape , shape_query_callback , NULL ) ;
}
@ -352,7 +346,7 @@ LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
{
cpShape * cur_shape = res - > shape ;
Entity * other = cp_shape_entity ( cur_shape ) ;
flight_assert ( other - > is_box | | other - > is_player | | other - > is_missile ) ;
flight_assert ( other - > is_box | | other - > is_player | | other - > is_missile | | other - > is_orb ) ;
cpVect to = cpvsub ( entity_pos ( other ) , entity_pos ( launcher ) ) ;
bool should_attack = true ;
@ -360,6 +354,8 @@ LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
should_attack = false ;
if ( other - > owning_squad = = launcher - > owning_squad )
should_attack = false ;
if ( other - > is_orb )
should_attack = true ;
if ( should_attack & & cpvlength ( to ) < nearest_dist )
{
@ -532,14 +528,26 @@ void entity_set_rotation(Entity *e, double rot)
void entity_set_pos ( Entity * e , cpVect pos )
{
flight_assert ( e - > is_grid ) ;
flight_assert ( e - > body ! = NULL ) ;
cpBodySetPosition ( e - > body , ( pos ) ) ;
}
// IMPORTANT: all shapes must exist in one of these categories, as by default chipmunk assigns an object
// to be in every category. Which is bad because that doesn't make sense for entities
enum
{
DEFAULT = 1 < < 0 ,
BOXES = 1 < < 1 ,
} ;
static const cpShapeFilter FILTER_ONLY_BOXES = { CP_NO_GROUP , BOXES , BOXES } ;
static const cpShapeFilter FILTER_BOXES = { CP_NO_GROUP , DEFAULT | BOXES , CP_ALL_CATEGORIES } ;
static const cpShapeFilter FILTER_DEFAULT = { CP_NO_GROUP , DEFAULT , CP_ALL_CATEGORIES } ;
# define PLAYER_FILTER FILTER_DEFAULT
// size is (1/2 the width, 1/2 the height)
void create_rectangle_shape ( GameState * gs , Entity * e , Entity * parent , cpVect pos , cpVect size , double mass )
{
// @Robust remove this garbage
if ( e - > shape ! = NULL )
{
cpSpaceRemoveShape ( gs - > space , e - > shape ) ;
@ -561,9 +569,18 @@ void create_rectangle_shape(GameState *gs, Entity *e, Entity *parent, cpVect pos
cpShapeSetUserData ( e - > shape , ( void * ) e ) ;
cpShapeSetMass ( e - > shape , mass ) ;
cpSpaceAddShape ( gs - > space , e - > shape ) ;
cpShapeSetFilter ( e - > shape , FILTER_DEFAULT ) ;
}
void create_circle_shape ( GameState * gs , Entity * e , double radius )
{
e - > shape = cpCircleShapeNew ( e - > body , ORB_RADIUS , cpv ( 0 , 0 ) ) ;
e - > shape_parent_entity = get_id ( gs , e ) ;
e - > shape_radius = radius ;
cpShapeSetMass ( e - > shape , ORB_MASS ) ;
cpShapeSetUserData ( e - > shape , ( void * ) e ) ;
cpSpaceAddShape ( gs - > space , e - > shape ) ;
cpShapeSetFilter ( e - > shape , FILTER_DEFAULT ) ;
}
# define PLAYER_SHAPE_FILTER cpShapeFilterNew(CP_NO_GROUP, PLAYERS, CP_ALL_CATEGORIES)
void create_player ( Player * player )
{
@ -583,6 +600,14 @@ void create_player(Player *player)
# endif
}
void create_orb ( GameState * gs , Entity * e )
{
create_body ( gs , e ) ;
create_circle_shape ( gs , e , ORB_RADIUS ) ;
e - > is_circle_shape = true ;
e - > is_orb = true ;
}
void create_missile ( GameState * gs , Entity * e )
{
create_body ( gs , e ) ;
@ -593,10 +618,11 @@ void create_missile(GameState *gs, Entity *e)
void create_player_entity ( GameState * gs , Entity * e )
{
e - > is_player = true ;
e - > always_visible = true ;
e - > no_save_to_disk = true ;
create_body ( gs , e ) ;
create_rectangle_shape ( gs , e , e , ( cpVect ) { 0 } , cpvmult ( PLAYER_SIZE , 0.5 ) , PLAYER_MASS ) ;
cpShapeSetFilter ( e - > shape , PLAYER_ SHAPE_ FILTER) ;
cpShapeSetFilter ( e - > shape , PLAYER_ FILTER) ;
}
void box_add_to_boxes ( GameState * gs , Entity * grid , Entity * box_to_add )
@ -622,7 +648,7 @@ void box_create(GameState *gs, Entity *new_box, Entity *grid, cpVect pos)
create_rectangle_shape ( gs , new_box , grid , pos , ( cpVect ) { halfbox , halfbox } , 1.0 ) ;
cpShapeSetFilter ( new_box - > shape , cpShapeFilterNew ( CP_NO_GROUP , BOXES , CP_ALL_CATEGORIES ) ) ;
cpShapeSetFilter ( new_box - > shape , FILTER_BOXES ) ;
box_add_to_boxes ( gs , grid , new_box ) ;
}
@ -969,9 +995,11 @@ Entity *box_grid(Entity *box)
return ( Entity * ) cpBodyGetUserData ( cpShapeGetBody ( box - > shape ) ) ;
}
// in local space
cpVect entity_shape_pos ( Entity * box )
cpVect entity_shape_pos ( Entity * e )
{
return ( cpShapeGetCenterOfGravity ( box - > shape ) ) ;
flight_assert ( e ! = NULL ) ;
flight_assert ( e - > shape ! = NULL ) ;
return ( cpShapeGetCenterOfGravity ( e - > shape ) ) ;
}
double entity_shape_mass ( Entity * box )
{
@ -1204,6 +1232,7 @@ SerMaybeFailure ser_fV2(SerState *ser, cpVect *var)
SerMaybeFailure ser_f ( SerState * ser , double * d )
{
float f ;
if ( ser - > serializing )
f = ( float ) * d ;
@ -1211,6 +1240,15 @@ SerMaybeFailure ser_f(SerState *ser, double *d)
SER_ASSERT ( ! isnan ( f ) ) ;
* d = f ;
return ser_ok ;
// if you're ever sketched out by floating point precision you can use this to test...
/* double f;
if ( ser - > serializing )
f = ( double ) * d ;
SER_VAR ( & f ) ;
SER_ASSERT ( ! isnan ( f ) ) ;
* d = f ;
return ser_ok ; */
}
SerMaybeFailure ser_bodydata ( SerState * ser , struct BodyData * data )
@ -1305,10 +1343,18 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
bool has_shape = ser - > serializing & & e - > shape ! = NULL ;
SER_VAR ( & has_shape ) ;
if ( has_shape )
{
SER_MAYBE_RETURN ( ser_fV2 ( ser , & e - > shape_size ) ) ;
SER_VAR ( & e - > is_circle_shape ) ;
if ( e - > is_circle_shape )
{
SER_MAYBE_RETURN ( ser_f ( ser , & e - > shape_radius ) ) ;
}
else
{
SER_MAYBE_RETURN ( ser_fV2 ( ser , & e - > shape_size ) ) ;
}
SER_MAYBE_RETURN ( ser_entityid ( ser , & e - > shape_parent_entity ) ) ;
Entity * parent = get_entity ( gs , e - > shape_parent_entity ) ;
SER_ASSERT ( parent ! = NULL ) ;
@ -1334,7 +1380,14 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_VAR ( & filter . mask ) ;
if ( ! ser - > serializing )
{
create_rectangle_shape ( gs , e , parent , shape_pos , e - > shape_size , shape_mass ) ;
if ( e - > is_circle_shape )
{
create_circle_shape ( gs , e , e - > shape_radius ) ;
}
else
{
create_rectangle_shape ( gs , e , parent , shape_pos , e - > shape_size , shape_mass ) ;
}
cpShapeSetFilter ( e - > shape , filter ) ;
}
}
@ -1382,12 +1435,17 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN ( ser_entityid ( ser , & e - > boxes ) ) ;
}
SER_VAR ( & e - > is_missile )
SER_VAR ( & e - > is_missile ) ;
if ( e - > is_missile )
{
SER_MAYBE_RETURN ( ser_f ( ser , & e - > time_burned_for ) ) ;
}
SER_VAR ( & e - > is_orb ) ;
if ( e - > is_orb )
{
}
SER_VAR ( & e - > is_box ) ;
if ( e - > is_box )
{
@ -1409,6 +1467,9 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN ( ser_entityid ( ser , & e - > player_who_is_inside_of_me ) ) ;
break ;
case BoxThruster :
SER_MAYBE_RETURN ( ser_f ( ser , & e - > thrust ) ) ;
SER_MAYBE_RETURN ( ser_f ( ser , & e - > wanted_thrust ) ) ;
break ;
case BoxGyroscope :
SER_MAYBE_RETURN ( ser_f ( ser , & e - > thrust ) ) ;
SER_MAYBE_RETURN ( ser_f ( ser , & e - > wanted_thrust ) ) ;
@ -1906,7 +1967,6 @@ static bool scanner_filter(Entity *e)
static void do_explosion ( GameState * gs , Entity * explosion , double dt )
{
double cur_explosion_damage = dt * EXPLOSION_DAMAGE_PER_SEC ;
cpVect explosion_origin = explosion - > explosion_pos ;
double explosion_push_strength = explosion - > explosion_push_strength ;
@ -2021,9 +2081,14 @@ bool batteries_have_capacity_for(GameState *gs, Entity *grid, double *energy_lef
return false ;
}
// returns any e nergy unable to burn
// returns any e ffectiveness
double batteries_use_energy ( GameState * gs , Entity * grid , double * energy_left_over , double energy_to_use )
{
if ( energy_to_use = = 0.0 )
{
return 1.0 ;
}
double energy_wanting_to_use = energy_to_use ;
if ( * energy_left_over > 0.0 )
{
double energy_to_use_from_leftover = fmin ( * energy_left_over , energy_to_use ) ;
@ -2039,10 +2104,13 @@ double batteries_use_energy(GameState *gs, Entity *grid, double *energy_left_ove
battery - > energy_used + = energy_to_burn_from_this_battery ;
energy_to_use - = energy_to_burn_from_this_battery ;
if ( energy_to_use < = 0.0 )
return 0 .0;
return 1 .0;
}
}
return energy_to_use ;
double to_return = 1.0 - ( energy_to_use / energy_wanting_to_use ) ;
flight_assert ( to_return > = 0.0 ) ;
flight_assert ( to_return < = 1.0 ) ;
return to_return ;
}
double sun_dist_no_gravity ( Entity * sun )
@ -2233,6 +2301,17 @@ void create_initial_world(GameState *gs)
}
# ifndef DEBUG_WORLD
Log ( " Creating release world \n " ) ;
# define ORB_AT(pos) \
{ \
Entity * orb = new_entity ( gs ) ; \
create_orb ( gs , orb ) ; \
entity_set_pos ( orb , pos ) ; \
}
for ( int x = - 10 ; x > - 1000 ; x - = 20 )
{
ORB_AT ( cpv ( x , 0.0 ) ) ;
}
create_bomb_station ( gs , ( cpVect ) { 800.0 , 800.0 } , BoxExplosive ) ;
// create_hard_shell_station(gs, (cpVect){800.0, 400.0}, BoxGyroscope);
create_bomb_station ( gs , ( cpVect ) { 800.0 , - 800.0 } , BoxCloaking ) ;
@ -2240,6 +2319,7 @@ void create_initial_world(GameState *gs)
create_hard_shell_station ( gs , ( cpVect ) { - 7000.0 , 200.0 } , BoxMerge ) ;
# else
Log ( " Creating debug world \n " ) ;
// pos, mass, radius
create_bomb_station ( gs , ( cpVect ) { - 5.0 , 0.0 } , BoxExplosive ) ;
create_bomb_station ( gs , ( cpVect ) { 0.0 , 5.0 } , BoxGyroscope ) ;
@ -2302,6 +2382,14 @@ void body_integrity_check(cpBody *body, void *data)
flight_assert ( cp_body_entity ( body ) - > exists ) ;
flight_assert ( cp_body_entity ( body ) - > body = = body ) ;
}
void player_get_in_seat ( GameState * gs , Player * player , Entity * seat )
{
Entity * p = get_entity ( gs , player - > entity ) ;
p - > currently_inside_of_box = get_id ( gs , seat ) ;
seat - > player_who_is_inside_of_me = get_id ( gs , p ) ;
if ( seat - > box_type = = BoxMedbay )
player - > last_used_medbay = p - > currently_inside_of_box ;
}
void process ( struct GameState * gs , double dt )
{
@ -2393,8 +2481,15 @@ void process(struct GameState *gs, double dt)
entity_ensure_in_orbit ( gs , p ) ;
if ( medbay ! = NULL )
{
exit_seat ( gs , medbay , p ) ;
p - > damage = 0.95 ;
if ( get_entity ( gs , medbay - > player_who_is_inside_of_me ) = = NULL )
{
player_get_in_seat ( gs , player , medbay ) ;
}
else
{
exit_seat ( gs , medbay , p ) ;
}
}
}
flight_assert ( p - > is_player ) ;
@ -2427,7 +2522,7 @@ void process(struct GameState *gs, double dt)
if ( seat_maybe_in = = NULL ) // not in any seat
{
cpPointQueryInfo query_info = { 0 } ;
cpShape * result = cpSpacePointQueryNearest ( gs - > space , ( world_hand_pos ) , 0.1 , cpShapeFilterNew ( CP_NO_GROUP , CP_ALL_CATEGORIES , BOXES ) , & query_info ) ;
cpShape * result = cpSpacePointQueryNearest ( gs - > space , ( world_hand_pos ) , 0.1 , FILTER_ONLY_BOXES , & query_info ) ;
if ( result ! = NULL )
{
Entity * potential_seat = cp_shape_entity ( result ) ;
@ -2453,10 +2548,7 @@ void process(struct GameState *gs, double dt)
// don't let players get inside of cockpits that somebody else is already inside of
if ( get_entity ( gs , potential_seat - > player_who_is_inside_of_me ) = = NULL )
{
p - > currently_inside_of_box = get_id ( gs , potential_seat ) ;
potential_seat - > player_who_is_inside_of_me = get_id ( gs , p ) ;
if ( potential_seat - > box_type = = BoxMedbay )
player - > last_used_medbay = p - > currently_inside_of_box ;
player_get_in_seat ( gs , player , potential_seat ) ;
}
}
}
@ -2506,7 +2598,7 @@ void process(struct GameState *gs, double dt)
if ( seat_inside_of = = NULL )
{
cpShapeSetFilter ( p - > shape , PLAYER_ SHAPE_ FILTER) ;
cpShapeSetFilter ( p - > shape , PLAYER_ FILTER) ;
cpBodyApplyForceAtWorldPoint ( p - > body , ( cpvmult ( movement_this_tick , PLAYER_JETPACK_FORCE ) ) , cpBodyGetPosition ( p - > body ) ) ;
cpBodySetTorque ( p - > body , rotation_this_tick * PLAYER_JETPACK_TORQUE ) ;
p - > damage + = cpvlength ( movement_this_tick ) * dt * PLAYER_JETPACK_SPICE_PER_SECOND ;
@ -2560,7 +2652,7 @@ void process(struct GameState *gs, double dt)
cpVect world_build = world_hand_pos ;
Entity * target_grid = grid_to_build_on ( gs , world_hand_pos ) ;
cpShape * maybe_box_to_destroy = cpSpacePointQueryNearest ( gs - > space , ( world_build ) , 0.01 , cpShapeFilterNew ( CP_NO_GROUP , CP_ALL_CATEGORI ES, BOXES ) , & info ) ;
cpShape * maybe_box_to_destroy = cpSpacePointQueryNearest ( gs - > space , ( world_build ) , 0.01 , cpShapeFilterNew ( CP_NO_GROUP , BOX ES, BOXES ) , & info ) ;
if ( maybe_box_to_destroy ! = NULL )
{
Entity * cur_box = cp_shape_entity ( maybe_box_to_destroy ) ;
@ -2650,6 +2742,7 @@ void process(struct GameState *gs, double dt)
else
{
entity_destroy ( gs , e ) ;
continue ;
}
continue ;
}
@ -2666,7 +2759,7 @@ void process(struct GameState *gs, double dt)
if ( ! e - > is_grid ) // grids aren't damaged (this edge case sucks!)
{
PROFILE_SCOPE ( " Grid processing " )
// PROFILE_SCOPE("Grid processing")
{
sqdist = cpvlengthsq ( cpvsub ( ( entity_pos ( e ) ) , ( entity_pos ( i . sun ) ) ) ) ;
if ( sqdist < ( i . sun - > sun_radius * i . sun - > sun_radius ) )
@ -2700,10 +2793,37 @@ void process(struct GameState *gs, double dt)
if ( e - > explosion_progress > = EXPLOSION_TIME )
{
entity_destroy ( gs , e ) ;
continue ;
}
}
}
if ( e - > is_orb )
{
PROFILE_SCOPE ( " Orb " )
{
circle_query ( gs - > space , entity_pos ( e ) , ORB_HEAT_MAX_DETECTION_DIST ) ;
cpVect final_force = cpv ( 0 , 0 ) ;
QUEUE_ITER ( & query_result , QueryResult , res )
{
Entity * potential_aggravation = cp_shape_entity ( res - > shape ) ;
if ( potential_aggravation - > is_box & & potential_aggravation - > box_type = = BoxThruster & & fabs ( potential_aggravation - > thrust ) > 0.1 )
{
final_force = cpvadd ( final_force , cpvmult ( cpvsub ( entity_pos ( potential_aggravation ) , entity_pos ( e ) ) , ORB_HEAT_FORCE_MULTIPLIER ) ) ;
}
}
if ( cpvlength ( final_force ) > ORB_MAX_FORCE )
{
final_force = cpvmult ( cpvnormalize ( final_force ) , ORB_MAX_FORCE ) ;
}
// add drag
final_force = cpvadd ( final_force , cpvmult ( entity_vel ( gs , e ) , - 1.0 * lerp ( ORB_DRAG_CONSTANT , ORB_FROZEN_DRAG_CONSTANT , e - > damage ) ) ) ;
cpBodyApplyForceAtWorldPoint ( e - > body , final_force , entity_pos ( e ) ) ;
e - > damage - = dt * ORB_HEAL_RATE ;
e - > damage = clamp01 ( e - > damage ) ;
}
}
if ( e - > is_missile )
{
PROFILE_SCOPE ( " Missile " )
@ -2718,10 +2838,11 @@ void process(struct GameState *gs, double dt)
Entity * explosion = new_entity ( gs ) ;
explosion - > is_explosion = true ;
explosion - > explosion_pos = entity_pos ( e ) ;
explosion - > explosion_vel = ( cpBodyGetVelocity ( e - > body ) ) ;
explosion - > explosion_vel = cpBodyGetVelocity ( e - > body ) ;
explosion - > explosion_push_strength = MISSILE_EXPLOSION_PUSH ;
explosion - > explosion_radius = MISSILE_EXPLOSION_RADIUS ;
entity_destroy ( gs , e ) ;
continue ;
}
}
}
@ -2832,9 +2953,11 @@ void process(struct GameState *gs, double dt)
double new_sun = clamp01 ( fabs ( cpvdot ( box_facing_vector ( cur_box ) , cpvnormalize ( cpvsub ( entity_pos ( i . sun ) , entity_pos ( cur_box ) ) ) ) ) ) ;
// less sun the farther away you are!
new_sun * = lerp ( 1.0 , 0.0 , clamp01 ( cpv length( cpvsub ( entity_pos ( cur_box ) , entity_pos ( i . sun ) ) ) / sun_dist_no_gravity ( i . sun ) ) ) ;
new_sun * = lerp ( 1.0 , 0.0 , clamp01 ( cpv dist ( entity_pos ( cur_box ) , entity_pos ( i . sun ) ) / sun_dist_no_gravity ( i . sun ) ) ) ;
cur_box - > sun_amount + = new_sun ;
}
cur_box - > sun_amount = clamp01 ( cur_box - > sun_amount ) ;
energy_to_add + = cur_box - > sun_amount * SOLAR_ENERGY_PER_SECOND * dt ;
}
}
@ -2853,7 +2976,7 @@ void process(struct GameState *gs, double dt)
flight_assert ( energy_to_add > = 0.0 ) ;
}
// any energy_to_add existing now can also be used to power thrusters/medbay
// any energy_to_add existing now can also be used to power thrusters/medbay . Kind of like a temporary separate battery
double non_battery_energy_left_over = energy_to_add ;
// use the energy, stored in the batteries, in various boxes
@ -2861,25 +2984,17 @@ void process(struct GameState *gs, double dt)
{
if ( cur_box - > box_type = = BoxThruster )
{
double energy_to_consume = cur_box - > wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt ;
if ( cur_box - > wanted_thrust = = 0.0 )
{
cur_box - > thrust = 0.0 ;
}
if ( energy_to_consume > 0.0 )
{
cur_box - > thrust = 0.0 ;
double energy_unconsumed = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , energy_to_consume ) ;
cur_box - > thrust = ( 1.0 - energy_unconsumed / energy_to_consume ) * cur_box - > wanted_thrust ;
if ( cur_box - > thrust > = 0.0 )
cpBodyApplyForceAtWorldPoint ( grid - > body , ( thruster_force ( cur_box ) ) , ( entity_pos ( cur_box ) ) ) ;
}
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , cur_box - > wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt ) ;
cur_box - > thrust = cur_box - > energy_effectiveness * cur_box - > wanted_thrust ;
if ( cur_box - > thrust > = 0.0 )
cpBodyApplyForceAtWorldPoint ( grid - > body , ( thruster_force ( cur_box ) ) , ( entity_pos ( cur_box ) ) ) ;
}
if ( cur_box - > box_type = = BoxGyroscope )
{
cur_box - > gyrospin_velocity = lerp ( cur_box - > gyrospin_velocity , cur_box - > thrust * 20.0 , dt * 5.0 ) ;
cur_box - > gyrospin_angle + = cur_box - > gyrospin_velocity * dt ;
// wrap to keep the number small
if ( cur_box - > gyrospin_angle > 2.0 * PI )
{
cur_box - > gyrospin_angle - = 2.0 * PI ;
@ -2888,6 +3003,7 @@ void process(struct GameState *gs, double dt)
{
cur_box - > gyrospin_angle + = 2.0 * PI ;
}
if ( cur_box - > wanted_thrust = = 0.0 )
{
cur_box - > thrust = 0.0 ;
@ -2895,51 +3011,38 @@ void process(struct GameState *gs, double dt)
double thrust_to_want = cur_box - > wanted_thrust ;
if ( cur_box - > wanted_thrust = = 0.0 )
thrust_to_want = clamp ( - cpBodyGetAngularVelocity ( grid - > body ) * GYROSCOPE_PROPORTIONAL_INERTIAL_RESPONSE , - 1.0 , 1.0 ) ;
double energy_to_consume = fabs ( thrust_to_want * GYROSCOPE_ENERGY_USED_PER_SECOND * dt ) ;
if ( energy_to_consume > 0.0 )
{
cur_box - > thrust = 0.0 ;
double energy_unconsumed = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , energy_to_consume ) ;
cur_box - > thrust = ( 1.0 - energy_unconsumed / energy_to_consume ) * thrust_to_want ;
if ( fabs ( cur_box - > thrust ) > = 0.0 )
cpBodySetTorque ( grid - > body , cpBodyGetTorque ( grid - > body ) + cur_box - > thrust * GYROSCOPE_TORQUE ) ;
}
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , fabs ( thrust_to_want * GYROSCOPE_ENERGY_USED_PER_SECOND * dt ) ) ;
cur_box - > thrust = cur_box - > energy_effectiveness * thrust_to_want ;
if ( fabs ( cur_box - > thrust ) > = 0.0 )
cpBodySetTorque ( grid - > body , cpBodyGetTorque ( grid - > body ) + cur_box - > thrust * GYROSCOPE_TORQUE ) ;
}
if ( cur_box - > box_type = = BoxMedbay )
{
Entity * potential_meatbag_to_heal = get_entity ( gs , cur_box - > player_who_is_inside_of_me ) ;
if ( potential_meatbag_to_heal ! = NULL )
{
double wanted_energy_use = fmin ( potential_meatbag_to_heal - > damage , PLAYER_ENERGY_RECHARGE_PER_SECOND * dt ) ;
if ( wanted_energy_use > 0.0 )
{
double energy_unconsumed = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , wanted_energy_use ) ;
potential_meatbag_to_heal - > damage - = ( 1.0 - energy_unconsumed / wanted_energy_use ) * wanted_energy_use ;
}
double wanted_energy_to_heal = fmin ( potential_meatbag_to_heal - > damage , PLAYER_ENERGY_RECHARGE_PER_SECOND * dt ) ;
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , wanted_energy_to_heal ) ;
potential_meatbag_to_heal - > damage - = wanted_energy_to_heal * cur_box - > energy_effectiveness ;
}
}
if ( cur_box - > box_type = = BoxCloaking )
{
double energy_unconsumed = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , CLOAKING_ENERGY_USE * dt ) ;
if ( energy_unconsumed > = CLOAKING_ENERGY_USE * dt )
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , CLOAKING_ENERGY_USE * dt ) ;
cur_box - > cloaking_power = lerp ( cur_box - > cloaking_power , cur_box - > energy_effectiveness , dt * 3.0 ) ;
if ( cur_box - > energy_effectiveness > = 1.0 )
{
cur_box - > cloaking_power = lerp ( cur_box - > cloaking_power , 0.0 , dt * 3.0 ) ;
}
else
{
cur_box - > cloaking_power = lerp ( cur_box - > cloaking_power , 1.0 , dt * 3.0 ) ;
rect_query ( gs - > space , ( BoxCentered ) {
. pos = entity_pos ( cur_box ) ,
. rotation = entity_rotation ( cur_box ) ,
// subtract a little from the panel size so that boxes just at the boundary of the panel
// aren't (sometimes cloaked)/(sometimes not) from floating point imprecision
. size = cpv ( CLOAKING_PANEL_SIZE - 0.03 , CLOAKING_PANEL_SIZE - 0.03 ) ,
. size = cpv ( CLOAKING_PANEL_SIZE / 2.0 - 0.03 , CLOAKING_PANEL_SIZE / 2.0 - 0.03 ) ,
} ) ;
QUEUE_ITER ( & query_result , QueryResult , res )
{
cpShape * shape = res - > shape ;
Entity * from_cloaking_box = cur_box ;
GameState * gs = entitys_gamestate ( from_cloaking_box ) ;
Entity * to_cloak = cp_shape_entity ( shape ) ;
to_cloak - > time_was_last_cloaked = elapsed_time ( gs ) ;
@ -2954,8 +3057,9 @@ void process(struct GameState *gs, double dt)
if ( cur_box - > missile_construction_charge < 1.0 )
{
double want_use_energy = dt * MISSILE_CHARGE_RATE ;
double energy_charged = want_use_energy - batteries_use_energy ( gs , grid , & non_battery_energy_left_over , want_use_energy ) ;
cur_box - > missile_construction_charge + = energy_charged ;
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , want_use_energy ) ;
cur_box - > missile_construction_charge + = cur_box - > energy_effectiveness * want_use_energy ;
}
if ( target . target_found & & cur_box - > missile_construction_charge > = 1.0 )
@ -2971,11 +3075,12 @@ void process(struct GameState *gs, double dt)
}
if ( cur_box - > box_type = = BoxScanner )
{
// set the nearest platonic solid! only on server as only the server sees everything
cur_box - > energy_effectiveness = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , SCANNER_ENERGY_USE * dt ) ;
// only the server knows all the positions of all the solids
if ( gs - > server_side_computing )
{
double energy_unconsumed = batteries_use_energy ( gs , grid , & non_battery_energy_left_over , SCANNER_ENERGY_USE * dt ) ;
if ( energy_unconsumed > = SCANNER_ENERGY_USE * dt )
if ( cur_box - > energy_effectiveness < 1.0 )
{
cur_box - > platonic_detection_strength = 0.0 ;
cur_box - > platonic_nearest_direction = ( cpVect ) { 0 } ;