void CHSAsteroid::DoCycle(void)
{
	CHSObject *cObj;
	CHSUniverse *uSrc;
	CHSShip *Target;
	int idx;
	double dDistance;

		
	  uSrc = uaUniverses.FindUniverse(GetUID());
	  if (!uSrc)
		  return;
	
	  // Grab all of the objects in the universe, and see if they're in the area.
	  for (idx = 0; idx < HS_MAX_OBJECTS; idx++)
	  {
		  cObj = uSrc->GetUnivObject(idx);
		  if (!cObj)
			  continue;
		  if (cObj->GetType() != HST_SHIP)
			  continue;

		  Target = (CHSShip *) cObj;
		  dDistance = Dist3D(GetX(),GetY(),GetZ(),Target->GetX(),Target->GetY(),Target->GetZ());
		  
		  if (dDistance > GetSize() * 100)
			  continue;

		  if (GetDensity() < getrandom(50 / Target->GetSize() * ((Target->GetSpeed() + 1) / 1000)))
			  continue;

		  int strength;

		  strength = getrandom(GetDensity() * Target->GetSize() * ((Target->GetSpeed() + 1) / 1000));

		  Target->m_hull_points -= strength;

		  Target->NotifySrooms("The ship shakes as asteroids impact on the hull");

		  	// Is hull < 0?
			if (Target->m_hull_points < 0)
			{
				Target->ExplodeMe();
				if (!hsInterface.HasFlag(m_objnum, TYPE_THING, THING_HSPACE_SIM))
					Target->KillShipCrew("THE SHIP EXPLODES!!");
			} 

	  }

}
void CHSBlackHole::DoCycle(void)
{
	CHSObject *cObj;
	CHSUniverse *uSrc;
	CHSShip *Target;
	int idx;
	double dDistance;

		
	  uSrc = uaUniverses.FindUniverse(GetUID());
	  if (!uSrc)
		  return;
	
	  // Grab all of the objects in the universe, and see if they're in the area.
	  for (idx = 0; idx < HS_MAX_OBJECTS; idx++)
	  {
		  cObj = uSrc->GetUnivObject(idx);
		  if (!cObj)
			  continue;
		  if (cObj->GetType() != HST_SHIP)
			  continue;

		  Target = (CHSShip *) cObj;
		  dDistance = Dist3D(GetX(),GetY(),GetZ(),Target->GetX(),Target->GetY(),Target->GetZ());
		  
		  if (dDistance > GetSize() * 100 - 0.01)
			  continue;

		  int strength;

		  strength = (GetSize() * 100) / dDistance * 100 - 100;

		  Target->MoveTowards(m_x, m_y, m_z, strength);

		  Target->m_hull_points -= strength;

		  Target->NotifySrooms("The hull buckles from the black hole's gravity.");

		  	// Is hull < 0?
			if (Target->m_hull_points < 0)
			{
				Target->ExplodeMe();
				if (!hsInterface.HasFlag(m_objnum, TYPE_THING, THING_HSPACE_SIM))
					Target->KillShipCrew("THE SHIP EXPLODES!!");
			} 

	  }

}
// check collision.
bool COGBonusPhysicalObject::CheckCollision (IOGPhysicalObject* _pObject)
{
    if (!m_pListener)
        return false;

	if (!m_bActive)
		return false;

	const IOGObb& obb = _pObject->GetOBB();
    if (Dist3D(m_vPosition, obb.m_vCenter) <= obb.m_Aabb.GetRadius())
    {
        IOGCollision collision;
        collision.pActorMissile = m_pActor;
		collision.pActorBot = _pObject->GetActor();
        if (m_pListener->OnCollision(collision))
        {
			return _pObject->RespondOnCollision(collision);
        }
    }
    return false;
}
Exemplo n.º 4
0
// Moves the missile along the current trajectory.
void CHSMissile::MoveTowardTarget()
{
    if (!m_pData)
    {
        return;
    }

    // Calculate per second speed
    HS_FLOAT32 fSpeed;

    fSpeed = m_speed * (.0002778f * HSCONF.cyc_interval);

    static double tX = 0.0, tY = 0.0, tZ = 0.0;
    double dist;

    if(NULL != m_target && HST_SHIP == m_target->GetType())
    {

        // get value from 0.0 - 1.0 where 1.0 is 100% visible
        float cloak_effect =
            static_cast<CHSShip* >(m_target)->CloakingEffect() * 100;

        // If the random value is less than the cloaking effect,
        // the missile still sees the ship and can update its
        // coordinates, otherwise, leave them at the previous
        // location
        if(hsInterface.GetRandom(100) <= (HS_UINT32) cloak_effect)
        {
            tX = m_target->GetX();
            tY = m_target->GetY();
            tZ = m_target->GetZ();
        }
    }
    else
    {
        tX = m_target->GetX();
        tY = m_target->GetY();
        tZ = m_target->GetZ();
    }

    dist = Dist3D(m_x, m_y, m_z, tX, tY, tZ);

    // Determine if speed is > distance, which might indicate
    // that the missile is within hitting range.  If this is
    // true, move the missile just the distance to the target
    // and see if the coordinates are relatively close.  It's
    // possible that the missile is close, but the target is
    // evading, in which case we just have to move the missile
    // it's regular distance.
    if (fSpeed > dist)
    {
        // Move just the distance
        double n_x, n_y, n_z;
        n_x = m_x + m_motion_vector.i() * dist;
        n_y = m_y + m_motion_vector.j() * dist;
        n_z = m_z + m_motion_vector.k() * dist;

        // Is new distance within 1 unit?
        dist = Dist3D(n_x, n_y, n_z, m_target->GetX(), m_target->GetY(),
                      m_target->GetZ());
        if (dist <= 1)
        {
            m_target_hit = true;
            return;
        }
    }

    // At this point we know we didn't hit, so just move regularly.
    m_x += m_motion_vector.i() * fSpeed;
    m_y += m_motion_vector.j() * fSpeed;
    m_z += m_motion_vector.k() * fSpeed;
}
Exemplo n.º 5
0
/*
 * This is called for all the polygons to delete them and replace them with
 * triangles around a centeral displaced point.  The check for which ones
 * to process and which to skip is the same as above.
 */
	static EDError
Subdivide (
	SpikeyData		*dat,
	const EDPolygonInfo	*pi)
{
	MeshEditOp		*op = dat->op;
	EDStateRef		 s = op->state;
	EDPointInfo		*vi;
	double			 cen[3], norm[3], d;
	LWPntID			 cg;
	LWPntID			 vl[3];
	int			 i;

	if (!( (pi->flags & EDDF_SELECT) && pi->numPnts >= 3 &&
	       (pi->type == LWPOLTYPE_FACE || pi->type == LWPOLTYPE_PTCH) ))
		return EDERR_NONE;

	/*
	 * Count this polygon in the aggregate for the monitor.  The
	 * step function returns True if the user has requested an abort,
	 * which we can propogate by returning the appropriate code.
	 */
	if (dat->mon && (*dat->mon->step) (dat->mon->data, 1))
		return EDERR_USERABORT;

	/*
	 * Compute the CG of the polygon vertices as `cen.'
	 */
	cen[0] = cen[1] = cen[2] = 0.0;
	for (i = 0; i < pi->numPnts; i++) {
		vi = (*op->pointInfo) (s, pi->points[i]);
		if (!vi)
			return EDERR_NOMEMORY;

		cen[0] += vi->position[0];
		cen[1] += vi->position[1];
		cen[2] += vi->position[2];
	}
	cen[0] = cen[0] / pi->numPnts;
	cen[1] = cen[1] / pi->numPnts;
	cen[2] = cen[2] / pi->numPnts;

	/*
	 * Compute the average distance from a polygon vertex to
	 * the center point.
	 */
	d = 0.0;
	for (i = 0; i < pi->numPnts; i++) {
		vi = (*op->pointInfo) (s, pi->points[i]);
		if (!vi)
			return EDERR_NOMEMORY;

		d += Dist3D (vi->position, cen);
	}
	d = d / pi->numPnts;

	/*
	 * Translate the center point out of the polygon's plane by this
	 * average distance times the spikeyness factor.  This translation
	 * can only be done if the polygon has a valid normal.
	 */
	d *= dat->spike;
	if (d && (*op->polyNormal) (op->state, pi->pol, norm)) {
		cen[0] += norm[0] * d;
		cen[1] += norm[1] * d;
		cen[2] += norm[2] * d;
	}

	/*
	 * Create a new point at the offset center position.  VMAP vectors
	 * will be an average of the values at the polygon vertices.
	 */
	cg = (*op->addIPnt) (s, cen, pi->numPnts, pi->points, NULL);
	if (!cg)
		return EDERR_NOMEMORY;

	/*
	 * Loop over points in the polygon and create new triangles
	 * from each pair to the center.  We use `addPoly' rather than
	 * `addTri' since we want to preserve the original polygon
	 * tags and sidedness.  Note the "modulo numPnts" to make
	 * the point index wrap around the end of the point array.
	 */
	vl[0] = cg;
	for (i = 0; i < pi->numPnts; i++) {
		vl[1] = pi->points[i];
		vl[2] = pi->points[(i + 1) % pi->numPnts];
		if (!(*op->addPoly) (s, pi->type, pi->pol, NULL, 3, vl))
			return EDERR_NOMEMORY;
	}

	/*
	 * Delete the orginal and we're done.
	 */
	return ((*op->remPoly) (op->state, pi->pol));
}
// Attacks a target object.
void CHSLaser::AttackObject(CHSObject *cSource,
							CHSObject *cTarget,
							CHSConsole *cConsole,
							int iSysType)
{
	dbref dbUser;
	int   iAttackRoll;
	int   iDefendRoll;
	int i;
	CHSObject *cCTarget;
	double sX, sY, sZ; // Source object coords
	double tX, tY, tZ; // Target object coords;

	// Grab the user of the console.
	dbUser = hsInterface.ConsoleUser(cConsole->m_objnum);

	// Can we attack that object?
	if (cSource->GetType() == HST_SHIP)
	{
		CHSSysCloak *cCloak;
		CHSShip *ptr;
		float rval;

		ptr = (CHSShip *)cSource;

		// Look for the cloaking device.
		cCloak = (CHSSysCloak *)ptr->GetEngSystem(HSS_CLOAK);
		if (cCloak)
			if (cCloak->GetEngaged())
			{
				if (dbUser != NOTHING)
					hsStdError(dbUser, "You cannot fire while cloaked.");
				return;
			}
	}

	if (!CanAttackObject(cTarget))
	{
		if (dbUser != NOTHING)
			hsStdError(dbUser,
			"You cannot attack that target with that weapon.");
	}

 	// Calculate distance to object
	sX = cSource->GetX();
	sY = cSource->GetY();
	sZ = cSource->GetZ();
	tX = cTarget->GetX();
	tY = cTarget->GetY();
	tZ = cTarget->GetZ();

	double dDistance;
	dDistance = Dist3D(sX, sY, sZ, tX, tY, tZ) + .00001;

	// Size of a target ship matters relative to distance.
	// The closer a target gets to the ship, the larger
	// it effectively is.  That is to say it takes up more
	// of the view angle.  When the target is right next
	// to the ship, in front of the gun, it is essentially
	// the broad side of a barn, which everyone can hit.
	// Thus, to handle this we'll calculate the size of
	// the target and the viewing angle it takes up.

	double dSize; // Size of the side of the target
	double dAngle; // Amount of viewing angle taken up by size

	dSize = cTarget->GetSize();
	dSize = (.7 * dSize) * (.7 * dSize);

	// Halve the size, and divide by distance.  This
	// gives us the tangent of the angle taken up by
	// the target.
	dSize = (dSize * .5) / dDistance;

	// Take the inverse tangent to get angle.
	dAngle = atan(dSize);

	// Double the angle because we used half of the size
	// to get the angle of a right triangle.
	dAngle *= 2;

	// We now have the viewing angle consumed by the 
	// target.  There's a maximum possible value of 180,
	// so divide by that to determine how much of the viewing
	// angle is taken up by the target.
	dSize = dAngle * .005555;

	// Subtract from 1 to get maximum values of 1 when the
	// angle is small.
	dSize = 1 - dSize;

	// Now multiply by 6 to get relative difficulty of hitting
	// target.
	iDefendRoll = (int) (6 * dSize) + getrandom(6);
    iAttackRoll = GetAccuracy() + getrandom(6);

	// Simulate difficulty when a target is moving.
	// If the target is moving toward or away from the
	// attacker, it's not very difficult.  Thus, we
	// calculate the change in angle for the target
	// during one cycle.  The maximum change is 180
	// degrees.
	CHSVector tVec;
	CHSVector aVec;
	tVec = cTarget->GetMotionVector();
	aVec = cSource->GetMotionVector();

	// Calculate vector to target now.
	double dx, dy, dz;
	dx = tX - sX;
	dy = tY - sY;
	dz = tZ - sZ;

	// Make a unit vector
	dx /= dDistance;
	dy /= dDistance;
	dz /= dDistance;

	CHSVector nowVec(dx, dy, dz);

	// Now calculate coordinate for source and target
	// in one cycle.
	double sX2, sY2, sZ2;
	double tX2, tY2, tZ2;
	double aSpeed, tSpeed;

	// Grab both object speeds, and bring them down
	// to per-second levels.
	aSpeed = cSource->GetSpeed() * .0002778;
	tSpeed = cTarget->GetSpeed() * .0002778;

	// Calculate coordinates for next cycle.
	sX2 = sX + (aVec.i() * aSpeed);
	sY2 = sY + (aVec.j() * aSpeed);
	sZ2 = sZ + (aVec.k() * aSpeed);
	tX2 = tX + (tVec.i() * tSpeed);
	tY2 = tY + (tVec.j() * tSpeed);
	tZ2 = tZ + (tVec.k() * tSpeed);

	// Calculate vector to target after next cycle
	dx = tX2 - sX2;
	dy = tY2 - sY2;
	dz = tZ2 - sZ2;

	// Divide by distance to make a unit vector
	double dDistance2;
	dDistance2 = Dist3D(sX2, sY2, sZ2, tX2, tY2, tZ2);
	dx /= dDistance2;
	dy /= dDistance2;
	dz /= dDistance2;

	CHSVector nextVec(dx, dy, dz);

	// Calculate the dot product between the previous
	// and the next cycle vectors.
	double dp;
	dp = nowVec.DotProduct(nextVec);

	// Calculate the angle change.  This is in radians.
	dAngle = acos(dp);

	// Now divide angle change by 2pi to get change in angle
	// from 0 to 1, where 1 is a huge change in angle and,
	// therefore, high difficulty.
	dAngle *= .15915;

	// Add up to 6 points of defense for "evasion" by angle
	// change.
	iDefendRoll += (int) (6 * dAngle);


	// If distance is farther than our range, the shot always
	// misses.

	double range;
	range = GetRange();
				
	CHSUniverse *uDest;
	char tbuf[256];
	char fstat1[128];
	char fstat2[128];

	if (dDistance >= range || iDefendRoll > iAttackRoll) {
		sprintf(fstat1, "%s%smisses%s",ANSI_HILITE,ANSI_GREEN,ANSI_NORMAL);
		sprintf(fstat2, "%s%smissed%s",ANSI_HILITE,ANSI_GREEN,ANSI_NORMAL);
	} else {
		sprintf(fstat1, "%s%shits%s",ANSI_HILITE,ANSI_RED,ANSI_NORMAL);
		sprintf(fstat2, "%s%shit%s",ANSI_HILITE,ANSI_RED,ANSI_NORMAL);
	}
		
	uDest = uaUniverses.FindUniverse(cSource->GetUID());

	CHSSysSensors *cSensors;
	SENSOR_CONTACT *cContactS;
	SENSOR_CONTACT *cContactD;
	for (i = 0; i < HS_MAX_ACTIVE_OBJECTS; i++)
	{
		cCTarget = uDest->GetActiveUnivObject(i);
		if (!cCTarget)
			continue;
		if (cCTarget == cSource || cCTarget == cTarget)
			continue;

		cSensors = (CHSSysSensors *)cCTarget->GetEngSystem(HSS_SENSORS);
		if (!cSensors)
			continue;

		cContactS = cSensors->GetContact(cSource);
		cContactD = cSensors->GetContact(cTarget);


		if (!cContactS && !cContactD)
			continue;

		if (!cContactS && cContactD) {
			if (cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact is being fired upon and %s",cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL, fstat2);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s is being fired upon and %s",cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat2);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}
			continue;
		}
						
											
		if (cContactS && !cContactD) {
			if (cContactS->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact is firing upon something",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s is firing upon something",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}
			continue;
		}

		if (cContactS && cContactD)
			if (cContactS->status == DETECTED && cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact fires and %s unknown contact %s[%s%s%d%s%s]%s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, fstat1,cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf,MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED && cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s fires and %s the %s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat1, cTarget->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED && cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s fires and %s unknown contact %s[%s%s%d%s%s]%s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat1,cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == DETECTED && cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact fires and %s the %s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, fstat1, cTarget->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}

	}
	
	
	
	
	
	if (dDistance >= range)
    {
		if (dbUser != NOTHING)
			hsStdError(
			dbUser,
			"Your shot dissipates short of its target.");

		strcpy(tbuf,
			"An incoming energy shot has missed us.");
		cTarget->HandleMessage(tbuf, MSG_COMBAT, (long *)cSource);
	}
    else if (iAttackRoll > iDefendRoll)
	{
		// The weapon hits!
		// Determine strength based on base weapon
		// strength and range to target.
		int strength;

		strength = GetStrength();
		if (dDistance > (range * .333))
		{
			strength = (int)(strength * 
				(.333 + (1 - (dDistance / (range + .0001)))));
		}

		// If iSysType is not HSS_NOTYPE, then do a roll
		// against the accuracy of the weapon to see if
		// the system gets hit.
		if (iSysType != HSS_NOTYPE)
		{
			UINT ARoll, SRoll;
		
			ARoll = getrandom(GetAccuracy());
			SRoll = getrandom(10);

			if (SRoll > ARoll)
				iSysType = HSS_NOTYPE; // Didn't succeed
		}

		// Tell the target to take damage
		cTarget->HandleDamage(cSource, this, strength,
			cConsole, iSysType);
	
	}
	else
	{
		// The weapon misses. :(
		if (dbUser != NOTHING)
			hsStdError(dbUser,
			"Your shot skims past your target and out into space.");

		strcpy(tbuf,
			"An incoming energy shot has missed us.");
		cTarget->HandleMessage(tbuf, MSG_COMBAT, (long *)cSource);
	}

	Regenerate();
}