⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waypoint.cpp

📁 空战游戏flacon源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	if (!flt)
		return;

	w = flt->GetFirstUnitWP ();
	i = 1;
	while (w && w != wp)
	{
		w = w->GetNextWP ();
		i++;
	}
	if (!w)
		return;

	// Paint leg red, if we have errors
	campID = flt->GetCampID();
	cwp = gMapMgr->GetCurWP();
	if (!cwp)
		return;
	if (!IsValidWP(w,flt))
		{
		cwp->SetState(campID*256+i,2);
		cwp->SetState(0x40000000+(campID*256)+i,2);
		}
	else if (w == flt->GetCurrentUnitWP())
		{
		cwp->SetState(campID*256+i,0);
		cwp->SetState(0x40000000+(campID*256)+i,1);
		}
	else
		{
		cwp->SetState(campID*256+i,0);
		cwp->SetState(0x40000000+(campID*256)+i,0);
		}
	cwp->Refresh();

	gActiveWPNum = static_cast<short>(i);

	if (gMainHandler)
		win = gMainHandler->FindWindow (FLIGHT_PLAN_WIN);

	if (win)
		{
		UpdateWaypointWindowInfo (win, wp, gActiveWPNum);
		win->RefreshWindow();
		}
	}

// We've changed waypoint wp's location, speed, or time and need to recalculate
void recalculate_waypoint_list (WayPointClass *wp, int minSpeed, int maxSpeed)
	{
	// First, find out if we're time locked ourselves
	if (wp->GetWPFlags() & WPF_TIME_LOCKED)
		{
		// We're gonna have to do two recalculations, one before and one after this waypoint
		WayPointClass	*pw,*nw;
		float			dist;
		int				time;
		pw = wp->GetPrevWP();
		nw = wp->GetNextWP();
		if (pw && !(pw->GetWPFlags() & WPF_TIME_LOCKED))
			recalculate_waypoint(pw, minSpeed, maxSpeed);
		else if (pw)
			{
			// Simply set Speed between pw and wp
			dist = wp->DistanceTo(pw);
			time = wp->GetWPArrivalTime() - pw->GetWPDepartureTime();
			if (time != 0)
				wp->SetWPSpeed((dist*CampaignHours)/time);
			else
				wp->SetWPSpeed(0);
			}
		if (nw && !(nw->GetWPFlags() & WPF_TIME_LOCKED))
			recalculate_waypoint(nw, minSpeed, maxSpeed);
		else if (nw)
			{
			// Simply set Speed between nw and wp
			dist = wp->DistanceTo(nw);
			time = nw->GetWPArrivalTime() - wp->GetWPDepartureTime();
			if (time != 0)
				nw->SetWPSpeed((dist*CampaignHours)/time);
			else
				nw->SetWPSpeed(0);
			}
		}
	else
		recalculate_waypoint(wp, minSpeed, maxSpeed);
	}

// We've changed waypoint wp's location, speed, or time and need to recalculate
void recalculate_waypoints (WayPointClass *wp)
	{
	FlightClass		*flt;
	int				minSpeed,maxSpeed;

	flt = (Flight) vuDatabase->Find (gActiveFlightID);
	if (!flt || !wp || !flt->IsFlight())
		return;

	minSpeed = flt->GetCruiseSpeed()/2;
	maxSpeed = flt->GetMaxSpeed();

	// Do the recalculation
	recalculate_waypoint_list(wp, minSpeed, maxSpeed);

	// Check for errors
	ValidateWayPoints(flt);

	// Refresh
	refresh_waypoint(wp);
	}

void recalculate_waypoint (WayPointClass *wp, int, int)
	{
	GridIndex		x,y,nx,ny;
	float			speed,dist,d;
	WayPointClass	*pw,*nw,*w;
	CampaignTime	startTime=0,endTime=0,lockedTime=0,now;

	if (!wp)
		return;

	ShiAssert(!(wp->GetWPFlags() & WPF_TIME_LOCKED));

	// KCK: This is annoyingly complex.
	// Basically, we're trying to either move times in/out from the changed waypoint
	// or smooth speeds between two time locked waypoints,

	// First, find out if we're between a time locked pair, or if we've got open ends
	pw = nw = wp;
	w = wp->GetPrevWP();
	while (w)
		{
		pw = w;
		if (w->GetWPFlags() & WPF_TIME_LOCKED)
			break;
		w = w->GetPrevWP();
		}
	w = wp->GetNextWP();
	while (w)
		{
		nw = w;
		if (w->GetWPFlags() & WPF_TIME_LOCKED)
			break;
		w = w->GetNextWP();
		}
	if ((pw->GetWPFlags() & WPF_TIME_LOCKED) && (nw->GetWPFlags() & WPF_TIME_LOCKED))
		{
		// We're between timelocked stuff. smooth the speeds
		startTime = pw->GetWPDepartureTime();
		endTime = nw->GetWPArrivalTime();
		// Now calculate the total adjustable distance and time
		dist = 0.0F;
		pw->GetWPLocation(&x,&y);
		w = pw->GetNextWP();
		while (w)
			{
			w->GetWPLocation(&nx,&ny);
			d = Distance(x,y,nx,ny);
			if (w->GetWPFlags() & WPF_SPEED_LOCKED)
				lockedTime += FloatToInt32((d * CampaignHours) / w->GetWPSpeed());		// This time is locked up
			else
				dist += d;
			x = nx;
			y = ny;
			if (w == nw)
				break;
			w = w->GetNextWP();
			}
		// Now calculate our new average speed and apply it
		if (startTime > endTime)
			speed = (dist * CampaignHours) / (((startTime - endTime)*-1) - lockedTime);
		else
			speed = (dist * CampaignHours) / ((endTime - startTime) - lockedTime);
		pw->GetWPLocation(&x,&y);
		now = startTime;
		w = pw->GetNextWP();
		while (w)
			{
			w->GetWPLocation(&nx,&ny);
			d = Distance(x,y,nx,ny);
			if (!(w->GetWPFlags() & WPF_SPEED_LOCKED))
				{
				w->SetWPSpeed(speed);
				if (speed)
					now += FloatToInt32((d * CampaignHours) / speed);
				}
			else if (w->GetWPSpeed())
				now += FloatToInt32((d * CampaignHours) / w->GetWPSpeed());
			if (w == nw)
				break;
			w->SetWPTimes(now);
			now += w->GetWPStationTime();
			x = nx;
			y = ny;
			w = w->GetNextWP();
			}
		}
	else
		{
		// We've got one or more open ends, adjust times while keeping speeds
		if (nw && (nw->GetWPFlags() & WPF_TIME_LOCKED))
			{
			// Push backwards from nw (keep speeds constant)
			now = nw->GetWPArrivalTime();
			nw->GetWPLocation(&x,&y);
			w = nw->GetPrevWP();
			while (w)
				{
				w->GetWPLocation(&nx,&ny);
				d = Distance(x,y,nx,ny);
				speed = nw->GetWPSpeed();
				if (speed)
					now -= FloatToInt32((d * CampaignHours) / speed);
				now -= w->GetWPStationTime();
				w->SetWPTimes(now);
				if (w == pw)
					break;
				x = nx;
				y = ny;
				nw = w;
				w = w->GetPrevWP();
				}
			}
		else if (pw)
			{
			// Push forward from pw
			now = pw->GetWPDepartureTime();
			pw->GetWPLocation(&x,&y);
			w = pw->GetNextWP();
			while (w)
				{
				w->GetWPLocation(&nx,&ny);
				d = Distance(x,y,nx,ny);
				speed = w->GetWPSpeed();
				if (speed)
					now += FloatToInt32((d * CampaignHours) / speed);
				w->SetWPTimes(now);
				now = w->GetWPDepartureTime();
				if (w == nw)
					break;
				x = nx;
				y = ny;
				w = w->GetNextWP();
				}
			}
		else
			ShiAssert(0);
		}
	}

int WayPointErrorCode (WayPointClass *wp, Flight flt)
	{
	WayPointClass	*pw;
	float			dist,speed,minSpeed,maxSpeed;
	int				errors=0,action;
	unsigned int	fuelAvail;
	long			time;
	CampaignTime	missionTime,takeoff,land;

	// Check for bad target/airbase/patrol times
	action = wp->GetWPAction();
	if (action == WP_TAKEOFF || action == WP_LAND || action == WP_STRIKE || action == WP_BOMB ||
		action == WP_INTERCEPT || action == WP_RECON || action == WP_NAVSTRIKE)
		{
		// Requires a valid campaign entity
		CampEntity ent = wp->GetWPTarget();
		if (!ent)
			errors |= WPERROR_NO_TARGET;
		}

	// Check for fuel
	pw = flt->GetFirstUnitWP();
	takeoff = land = pw->GetWPDepartureTime();
	while (pw && pw->GetWPAction() != WP_LAND)
		pw = pw->GetNextWP();
	if (pw)
		land = pw->GetWPArrivalTime();
	missionTime = land-takeoff;
	fuelAvail = flt->CalculateFuelAvailable(255);
	if ((missionTime/CampaignMinutes) * flt->GetUnitClassData()->Rate > fuelAvail)
		errors |= WPERROR_FUEL;

	// Do minimum speed checks
	minSpeed = flt->GetCruiseSpeed()/2.0F - 20.0F;
	maxSpeed = flt->GetMaxSpeed() + 20.0F;
	if ((wp->GetWPFlags() & WPF_ALTERNATE) || wp->GetWPAction() == WP_REFUEL)
		return errors;
	if (wp->GetWPSpeed() < minSpeed && wp->GetPrevWP())
		errors |= WPERROR_SPEED;
	if (wp->GetWPSpeed() > maxSpeed)
		errors |= WPERROR_SPEED;

	// Check for valid speeds/times
	pw = wp->GetPrevWP();
	if (pw)
		{
		time = wp->GetWPArrivalTime() - pw->GetWPDepartureTime();
		if (time <= 1)
			errors |= WPERROR_TIME;
		dist = wp->DistanceTo(pw);
		if (time)
			speed = (dist * CampaignHours) / time;
		else
			speed = 0.0F;
		if (speed < minSpeed || speed > maxSpeed || fabs(speed - wp->GetWPSpeed()) > 10.0F)
			errors |= WPERROR_SPEED;
		}
	return errors;
	}

int IsValidWP (WayPointClass *wp, Flight flt)
	{
	int				errors;

	errors = WayPointErrorCode(wp, flt);
	if (errors)
		return FALSE;
	return TRUE;
	}

void ValidateWayPoints (Flight flt)
	{
	C_Waypoint		*cwp;
	WayPoint		w;
	int				i=1;
	int				campID;

	if (!flt)
		return;

	campID = flt->GetCampID();
	cwp = gMapMgr->GetCurWP();
	w = flt->GetFirstUnitWP();
	while (w)
		{
		if (!IsValidWP(w,flt))
			{
			cwp->SetState(campID*256+i,2);
			cwp->SetState(0x40000000+(campID*256)+i,2);
			}
		else if (w == flt->GetCurrentUnitWP())
			{
			cwp->SetState(campID*256+i,0);
			cwp->SetState(0x40000000+(campID*256)+i,1);
			}
		else
			{
			cwp->SetState(campID*256+i,0);
			cwp->SetState(0x40000000+(campID*256)+i,0);
			}
		i++;
		w = w->GetNextWP();
		}
	cwp->Refresh();
	}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void set_waypoint_climb_mode(long,short hittype,C_Base *control)
{
	C_ListBox
		*lbox;

	WayPointClass
		*wp;

	C_Window
		*win;

	if(hittype != C_TYPE_SELECT)
		return;

	win=control->Parent_;
	if(!win)
		return;

	lbox = (C_ListBox*) control;

	wp = get_current_waypoint ();

	if ((lbox) && (wp))
	{
		if(lbox->GetTextID() == CLIMB_DELAY)
			wp->SetWPFlag(WPF_HOLDCURRENT);
		else
			wp->UnSetWPFlag(WPF_HOLDCURRENT);
	}
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void set_waypoint_enroute_action(long,short hittype,C_Base *control)
{
	C_ListBox
		*lbox;

	WayPointClass
		*wp;

	C_Window
		*win;

	if(hittype != C_TYPE_SELECT)
		return;

	win=control->Parent_;
	if(!win)
		return;

	lbox = (C_ListBox*) control;

	wp = get_current_waypoint ();

	if ((lbox) && (wp))
		wp->SetWPRouteAction(lbox->GetTextID()-1);
	
	refresh_waypoint(wp);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void set_waypoint_action (WayPoint wp, int action)
	{
	int				flags,oldaction,oldflags;
	WayPoint		pw;
	CampBaseClass	*ent;
	GridIndex		x,y,ex=-1,ey=-1;

	if (!wp)
		return;

	oldaction = wp->GetWPAction();
	oldflags = wp->GetWPFlags();
	flags=0;
	switch (action)
		{
		case WP_TAKEOFF:
			flags=WPF_TAKEOFF;
			// Look for an airbase
			wp->GetWPLocation(&x,&y);
			ent = GetObjectiveByXY(x,y);
			if (ent && (ent->GetType() == TYPE_AIRBASE || ent->GetType() == TYPE_AIRSTRIP))
				wp->SetWPTarget(ent->Id());
			else
				wp->SetWPTarget(FalconNullId);
			break;
		case WP_LAND:
			flags=WPF_LAND;
			// Look for an airbase
			wp->GetWPLocation(&x,&y);
			ent = GetObjectiveByXY(x,y);
			if (ent && (ent->GetType() == TYPE_AIRBASE || ent->GetType() == TYPE_AIRSTRIP))
				wp->SetWPTarget(ent->Id());
			else
				wp->SetWPTarget(FalconNullId);
			break;
		case WP_ASSEMBLE:
		case WP_POSTASSEMBLE:
			flags=WPF_ASSEMBLE;
			wp->SetWPTarget(FalconNullId);
			break;
		case WP_TANKER:
		case WP_JAM:
		case WP_SAD:
		case WP_ELINT:
			flags=WPF_TARGET;
			pw = wp->GetPrevWP();
			if (pw && pw->GetWPAction() == action)
				flags |= WPF_REPEAT;
			wp->SetWPTarget(FalconNullId);
			break;
		case WP_GNDSTRIKE:
		case WP_CAP:
			flags=WPF_TARGET;
			pw = wp->GetPrevWP();
			if (pw && pw->GetWPAction() == action)
				flags |= WPF_REPEAT;
			else if (pw)
				{
				pw = wp->GetNextWP();
				if (pw && pw->GetWPAction() == action)
					flags |= WPF_CP;
				}
			break;
		case WP_ESCORT:
		case WP_CA:
		case WP_RESCUE:
		case WP_ASW:
			flags=WPF_TARGET;
			break;
		case WP_AIRDROP:
			flags=WPF_TARGET | WPF_LAND | WPF_TAKEOFF;
			break;
		case WP_PICKUP:
			flags=WPF_LAND | WPF_TAKEOFF;
			break;
		case WP_INTERCEPT:
		case WP_NAVSTRIKE:
		case WP_SEAD:
			flags=WPF_TARGET;
			// Look for a unit target
			wp->GetWPLocation(&x,&y);
			ent = wp->GetWPTarget();
			if (ent && ent->IsUnit())
				ent->GetLocation(&ex,&ey);
			if (x != ex || y != ey)
				{
				ent = GetUnitByXY(x,y);
				if (ent)
					wp->SetWPTarget(ent->Id());
				else
					wp->SetWPTarget(FalconNullId);
				}
			break;
		case WP_STRIKE:
		case WP_BOMB:
		case WP_RECON:
			flags=WPF_TARGET;
			// Look for an objective target
			wp->GetWPLocation(&x,&y);
			ent = wp->GetWPTarget();
			if (ent && ent->IsObjective())
				ent->GetLocation(&ex,&ey);
			if (x != ex || y != ey)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -