void
NetGameClient::DoObjDamage(NetMsg* msg)
{
	if (!msg) return;

	NetObjDamage obj_damage;
	obj_damage.Unpack(msg->Data());

	Ship* ship = FindShipByObjID(obj_damage.GetObjID());
	if (ship) {
		Sim*        sim         = Sim::GetSim();
		Shot*       shot        = FindShotByObjID(obj_damage.GetShotID());
		const Ship* owner       = 0;
		const char* owner_name  = "[NET]";

		ship->InflictNetDamage(obj_damage.GetDamage(), shot);

		if (shot && sim) {
			if (shot->Owner()) {
				owner       = shot->Owner();
				owner_name  = owner->Name();
			}

			if (shot->IsMissile()) {
				SimRegion*  region = ship->GetRegion();
				float       scale  = ship->Design()->explosion_scale;

				if (scale <= 0)
				scale = ship->Design()->scale;

				if (owner) {
					const ShipDesign* owner_design = owner->Design();
					if (owner_design && owner_design->scale < scale)
					scale = (float) owner_design->scale;
				}

				sim->CreateExplosion(shot->Location(), Point(), Explosion::SHOT_BLAST, 20.0f * scale, scale, region);
			}

			if (!shot->IsBeam()) {
				if (owner) {
					ShipStats* stats = ShipStats::Find(owner_name);

					if (stats) {
						if (shot->IsPrimary())
						stats->AddGunHit();
						else if (shot->Damage() > 0)
						stats->AddMissileHit();
					}
				}

				shot->Destroy();
			}
		}
	}
}
示例#2
0
Shot*
Weapon::FireBarrel(int n)
{
    const Point&   base_vel = ship->Velocity();
    Shot*          shot     = 0;
    SimRegion*     region   = ship->GetRegion();

    if (!region || n < 0 || n >= nbarrels || Game::Paused())
    return 0;

    firing = 1;
    Aim();

    Camera rail_cam;
    rail_cam.Clone(aim_cam);

    Point shotpos = muzzle_pts[n];
    if (design->length > 0)
    shotpos = shotpos + aim_cam.vpn() * design->length;

    // guns may be slewed towards target:
    if (design->primary) {
        shot = CreateShot(shotpos, aim_cam, design, ship);

        if (shot) {
            shot->SetVelocity(shot->Velocity() + base_vel);
        }
    }

    // missiles always launch in rail direction:
    else {
        // unless they are on a mobile launcher
        if (turret && design->self_aiming) {
            shot = CreateShot(shotpos, aim_cam, design, ship);
            shot->SetVelocity(base_vel);
        }
        else {
            shot = CreateShot(shotpos, rail_cam, design, ship);
            if (shot /* && !turret */) {
                Matrix orient = ship->Cam().Orientation();
                if (aim_azimuth != 0)   orient.Yaw(aim_azimuth);
                if (aim_elevation != 0) orient.Pitch(aim_elevation);

                Point eject = design->eject * orient;
                shot->SetVelocity(base_vel + eject);
            }
        }

        if (shot && visible_stores[n]) {
            GRAPHIC_DESTROY(visible_stores[n]);
        }
    }

    if (shot) {
        if (ammo > 0)
        ammo--;

        if (guided && target)
        shot->SeekTarget(target, subtarget);

        float shot_load;
        if (energy > design->charge)
        shot_load = design->charge;
        else
        shot_load = energy;   

        energy -= shot_load;
        shot->SetCharge(shot_load * availability);

        if (target && design->flak && !design->guided) {
            double speed = shot->Velocity().length();
            double range = (target->Location() - shot->Location()).length();

            if (range > design->min_range && range < design->max_range) {
                shot->SetFuse(range / speed);
            }
        }

        region->InsertObject(shot);

        if (beams) {
            beams[n] = shot;
            Observe(beams[n]);

            // aim beam at target:
            SetBeamPoints(true);
        }

        if (ship) {
            ShipStats* stats = ShipStats::Find(ship->Name());

            if (design->primary)
            stats->AddGunShot();
            else if (design->decoy_type == 0 && design->damage > 0)
            stats->AddMissileShot();
        }
    }

    return shot;
}