📄 waypoint.cpp
字号:
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 + -