void check_gravity(entity *e)
{
int heightvar;
entity *other = NULL, *dust, *tempself, *plat = NULL;
s_collision_attack attack;
float gravity;
float fmin, fmax;
if(e->update_mark & 8)
{
return;
}
tempself = self;
self = e;
adjust_base(self, &plat);
if(!is_frozen(self) )// Incase an entity is in the air, don't update animations
{
if(self->animation->size.y)
{
heightvar = self->animation->size.y;
}
else
{
heightvar = self->modeldata.size.y;
}
// White Dragon: turn-off the hitwall flag if you're not near a obstacle. this help to avoid a hit loop
/*if( (self->position.y <= self->base || !inair(self)) && self->velocity.y <= 0)
{
if ( self->hitwall && !is_obstacle_around(self,1.0) ) self->hitwall = 0;
}*/
if((self->falling || self->velocity.y || self->position.y != self->base) && self->toss_time <= time)
{
if(heightvar && self->modeldata.subject_to_platform > 0 && self->velocity.y > 0)
{
other = check_platform_above_entity(self);
}
else
{
other = NULL;
}
if( other && other->position.y <= self->position.y + heightvar && !other->modeldata.nohithead)
{
if(self->hithead == NULL) // bang! Hit the ceiling.
{
self->velocity.y = 0;
self->hithead = other;
execute_onblocka_script(self, other);
}
}
else
{
self->hithead = NULL;
}
// gravity, antigravity factors
self->position.y += self->velocity.y * 100.0 / GAME_SPEED;
if(self->animation->antigrav)
{
gravity = 0;
}
else
{
gravity = (level ? level->gravity : default_level_gravity) * (1.0 - self->modeldata.antigravity);
}
if(self->modeldata.subject_to_gravity > 0)
{
self->velocity.y += gravity * 100.0 / GAME_SPEED;
}
fmin = (level ? level->maxfallspeed : default_level_maxfallspeed);
fmax = (level ? level->maxtossspeed : default_level_maxtossspeed);
if(self->velocity.y < fmin)
{
self->velocity.y = fmin;
}
else if(self->velocity.y > fmax)
{
self->velocity.y = fmax;
}
// Dropframe set?
if(self->animation->dropframe)
{
// If falling and frame has not
// passed dropframe, set frame to dropframe.
if(self->velocity.y <= 0 && self->animpos < self->animation->dropframe->frame) // begin dropping
{
update_frame(self, self->animation->dropframe->frame);
}
}
if (self->velocity.y)
{
execute_onmovea_script(self); //Move A event.
}
if( self->idling && validanim(self, ANI_WALKOFF) && diff(self->position.y, self->base) > T_WALKOFF )
{
entity *cplat = check_platform_below(self->position.x,self->position.z-1.0,self->position.y,self);
// White Dragon: fix for too low velocityz
if ( !cplat || (cplat && diff(get_platform_base(cplat),self->position.y) > T_WALKOFF) )
{
self->idling = 0;
self->takeaction = common_walkoff;
ent_set_anim(self, ANI_WALKOFF, 0);
self->landed_on_platform = plat = NULL;
}
}
// UTunnels: tossv <= 0 means land, while >0 means still rising, so
// you wont be stopped if you are passing the edge of a wall
if( (self->position.y <= self->base || !inair(self)) && self->velocity.y <= 0)
{
self->position.y = self->base;
self->falling = 0;
if ( self->hitwall ) self->hitwall = 0;
//self->projectile = 0;
// cust dust entity
if(self->modeldata.dust.fall_land >= 0 && self->velocity.y < -1 && self->drop)
{
dust = spawn(self->position.x, self->position.z, self->position.y, self->direction, NULL, self->modeldata.dust.fall_land, NULL);
if(dust)
{
dust->base = self->position.y;
dust->autokill = 2;
execute_onspawn_script(dust);
}
}
// bounce/quake
if(tobounce(self) && self->modeldata.bounce)
{
int i;
self->velocity.x /= self->animation->bounce;
self->velocity.z /= self->animation->bounce;
toss(self, (-self->velocity.y) / self->animation->bounce);
if(level && !(self->modeldata.noquake & NO_QUAKE))
{
level->quake = 4; // Don't shake if specified
}
if(SAMPLE_FALL >= 0)
{
sound_play_sample(SAMPLE_FALL, 0, savedata.effectvol, savedata.effectvol, 100);
}
if(self->modeldata.type & TYPE_PLAYER)
{
control_rumble(self->playerindex, 100 * (int)self->velocity.y / 2);
}
for(i = 0; i < MAX_PLAYERS; i++)
{
control_rumble(i, 75 * (int)self->velocity.y / 2);
}
}
else if((!self->animation->move[self->animpos]->base || self->animation->move[self->animpos]->base < 0) &&
(!self->animation->move[self->animpos]->y || self->animation->move[self->animpos]->y <= 0))
{
if( !(self->modeldata.aimove & AIMOVE1_BOOMERANG) ) self->velocity.x = self->velocity.z = self->velocity.y = 0;
}
else
{
self->velocity.y = 0;
}
if(plat && !self->landed_on_platform && self->position.y <= plat->position.y + plat->animation->platform[plat->animpos][7])
{
self->landed_on_platform = plat;
}
if(self->animation->landframe.frame >= 0 //Has landframe?
&& self->animation->landframe.frame <= self->animation->numframes //Not over animation frame count?
&& self->animpos < self->animation->landframe.frame) //Not already past landframe?
{
if(self->animation->landframe.ent >= 0)
{
dust = spawn(self->position.x, self->position.z, self->position.y, self->direction, NULL, self->animation->landframe.ent, NULL);
if(dust)
{
dust->base = self->position.y;
dust->autokill = 2;
execute_onspawn_script(dust);
}
}
update_frame(self, self->animation->landframe.frame);
}
// takedamage if thrown or basted
if(self->damage_on_landing > 0 && !self->dead)
{
if(self->takedamage)
{
attack = emptyattack;
attack.attack_force = self->damage_on_landing;
attack.attack_type = ATK_LAND;
self->takedamage(self, &attack);
}
else
{
self->health -= (self->damage_on_landing * self->defense[ATK_LAND].factor);
if(self->health <= 0 )
{
kill(self);
}
self->damage_on_landing = 0;
}
}
// in case landing, set hithead to NULL
self->hithead = NULL;
}// end of if - land checking
}// end of if - in-air checking
if(self->toss_time <= time)
{
self->toss_time = time + 1;
}
}//end of if
self->update_mark |= 8;
self = tempself;
}