void PhysicalObj::UpdatePosition() { // No ghost allowed here ! if (IsGhost()) { return; } if (m_collides_with_ground) { // object is not moving if (!IsMoving()) { // and has no reason to move if (!FootsInVacuum()) { if (!IsInWater()) { return; } } else { // it should fall ! StartMoving(); } } } // Compute new position. RunPhysicalEngine(); if (IsGhost()) { return; } // Classical object sometimes sinks in water and sometimes goes out of water! if (m_collides_with_ground) { if (IsInWater() && m_alive!=DROWNED && m_alive!=DEAD) Drown(); else if (!IsInWater() && m_alive==DROWNED) GoOutOfWater(); } }
void PhysicalObj::SetEnergyDelta(int delta, Character* /*dealer*/) { if (m_energy == -1) return; m_energy += delta; if (m_energy <= 0 && !IsGhost()) { Ghost(); m_energy = -1; } }
// called when a monster die [give exp/give extra drop] bool CMonster::OnDie( ) { CMap* map = GServer->MapList.Index[Position->Map]; if(map->ghost!=0) { if((map->IsNight( ) || map->ghost==2) && !IsGhost( ) && !IsGhostSeed( ) && !IsSummon( )) { UINT gs = GServer->RandNumber( 0, 100 ); if(gs<30) // 30% / 70% { // spawn a ghost seed [for now will be 701 [level 1 ghost seed] ] map->AddMonster( 701, Position->current, 0, NULL, NULL, Position->respawn, true ); } } } //LMA begin //CF mode 1 //20070621-211100 UINT special_exp=0; UINT special_lvl=0; if (map->is_cf==1) { //what monster is dead? if(this->montype==map->id_def_mon) { //oh my god, they killed a j&b !! (or the monster with exp) special_exp=(UINT) map->mon_lvl; special_lvl= (UINT) map->mon_exp; } else { if (this->montype!=map->id_temp_mon) { UINT gs = GServer->RandNumber( 0, 100 ); if(gs<map->percent) { //we use the temporary monster as a decoy. fPoint position_cf = GServer->RandInCircle( Position->current, 50 ); CMonster* monster2 = map->AddMonster( map->id_temp_mon, position_cf, 0, NULL, NULL, 0, true ); } } } } GServer->GiveExp( this , special_lvl, special_exp ); //LMA End return true; }
// called when we create a new monster [attack players?] bool CMonster::OnSpawn( bool Attack ) { lastSighCheck = clock(); if(IsGhost( ) && Attack ) { CPlayer* player = GetNearPlayer( ); if(player==NULL) // no players or too far return true; StartAction( (CCharacter*)player, NORMAL_ATTACK, 0 ); } return true; }
// Move to a point with collision test collision_t PhysicalObj::NotifyMove(Point2d oldPos, Point2d newPos) { if (IsGhost()) return NO_COLLISION; Point2d contactPos; Double contactAngle; Point2d pos, offset; PhysicalObj* collided_obj = NULL; collision_t collision = NO_COLLISION; // Convert meters to pixels. oldPos *= PIXEL_PER_METER; newPos *= PIXEL_PER_METER; // Compute distance between old and new position. Double lg = oldPos.SquareDistance(newPos); MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), square distance: %s", GetName().c_str(), Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(), Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(), Double2str(lg).c_str()); if (!lg.IsNotZero()) return NO_COLLISION; // Compute increments to move the object step by step from the old // to the new position. lg = sqrt(lg); offset = (newPos - oldPos) / lg; // First iteration position. pos = oldPos + offset; if (!m_collides_with_ground || IsInWater()) { MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), collides ground:%d, water:%d", GetName().c_str(), Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(), Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(), m_collides_with_ground, IsInWater()); SetXY(newPos); return NO_COLLISION; } do { Point2i tmpPos(uround(pos.x), uround(pos.y)); // Check if we exit the GetWorld(). If so, we stop moving and return. if (IsOutsideWorldXY(tmpPos)) { if (!GetWorld().IsOpen()) { tmpPos.x = InRange_Long(tmpPos.x, 0, GetWorld().GetWidth() - GetWidth() - 1); tmpPos.y = InRange_Long(tmpPos.y, 0, GetWorld().GetHeight() - GetHeight() - 1); MSG_DEBUG("physic.state", "%s - DeplaceTestCollision touche un bord : %d, %d", GetName().c_str(), tmpPos.x, tmpPos.y); collision = COLLISION_ON_GROUND; break; } SetXY(pos); MSG_DEBUG("physic.move", "%s moves (%f, %f) -> (%f, %f) : OUTSIDE WORLD", GetName().c_str(), oldPos.x.tofloat(), oldPos.y.tofloat(), newPos.x.tofloat(), newPos.y.tofloat()); return NO_COLLISION; } // Test if we collide... collided_obj = CollidedObjectXY(tmpPos); if (collided_obj) { if (!m_go_through_objects || m_last_collided_object != collided_obj) { MSG_DEBUG("physic.state", "%s collide on %s", GetName().c_str(), collided_obj->GetName().c_str()); if (m_go_through_objects) { SignalObjectCollision(GetSpeed(), collided_obj, collided_obj->GetSpeed()); collision = NO_COLLISION; } else { collision = COLLISION_ON_OBJECT; } m_last_collided_object = collided_obj; } else { collided_obj = NULL; collision = NO_COLLISION; } } else if (!IsInVacuumXY(tmpPos, false)) { collision = COLLISION_ON_GROUND; m_last_collided_object = NULL; } if (collision != NO_COLLISION) { // Nothing more to do! MSG_DEBUG("physic.state", "%s - Collision at %d,%d : on %s", GetName().c_str(), tmpPos.x, tmpPos.y, collision == COLLISION_ON_GROUND ? "ground" : "an object"); // Set the object position to the current position. SetXY(Point2d(pos.x - offset.x, pos.y - offset.y)); break; } // Next motion step pos += offset; lg -= ONE; } while (ZERO < lg); Point2d speed_before_collision = GetSpeed(); Point2d speed_collided_obj; if (collided_obj) { speed_collided_obj = collided_obj->GetSpeed(); } ContactPointAngleOnGround(pos, contactPos, contactAngle); Collide(collision, collided_obj, pos); // =================================== // it's time to signal object(s) about collision! // WARNING: the following calls can send Action(s) over the network (cf bug #11232) // Be sure to keep it isolated here // =================================== ActiveTeam().AccessWeapon().NotifyMove(!!collision); switch (collision) { case NO_COLLISION: // Nothing more to do! break; case COLLISION_ON_GROUND: SignalGroundCollision(speed_before_collision, contactAngle); break; case COLLISION_ON_OBJECT: SignalObjectCollision(speed_before_collision, collided_obj, speed_collided_obj); collided_obj->SignalObjectCollision(speed_collided_obj, this, speed_before_collision); break; } // =================================== return collision; }
void Plane::Draw() { if (IsGhost()) return; image->Draw(GetPosition()); }