// // SINGLE-PLAYER MISSION OBJECTIVES // #include #include #include "types.h" #include "Objectives.h" #include "shipselect.h" #include "KASFunc.h" #include "memory.h" #include "Strings.h" #include "font.h" #include "render.h" #include "feflow.h" #include "mainrgn.h" #include "sensors.h" #include "universe.h" #include "taskbar.h" #include "kasfunc.h" #include "SaveGame.h" #include "fontreg.h" #include "singleplayer.h" #include "soundevent.h" #include "AIVar.h" #include "nis.h" #include "subtitle.h" extern sdword popupTextNumLines; extern char *getWord(char *dest, char *source); // defined in researchgui.c extern regionhandle ghMainRegion; // for objective status overlay extern fonthandle selGroupFont2; #define OBJECTIVE_TITLE_TEXTCOLOR colRGB(255, 255, 255) #define OBJECTIVE_TEXTCOLOR colRGB(200, 200, 0) #define OBJECTIVE_POPUPTEXT_COLOR colRGB(0, 200, 200) #define PO_FONTNAMESIZE 64 #define poPopupFont selGroupFont2 LinkedList poFleetIntelligence; Objective **objectives = NULL; sdword objectivesAllocated = 0, objectivesUsed = 0; FleetIntelligence *poCurFleetIntelligence = NULL; regionhandle poBaseRegion = NULL; char poHeadingFontName[PO_FONTNAMESIZE]="blah blah blah blah blah blah"; char poTextFontName[PO_FONTNAMESIZE]="blah blah blah blah blah blah "; fonthandle poHeadingFont = 0; fonthandle poTextFont = 0; // Forward reference for callback tables void poClose(char *string, featom *atom); void poBackgroundDraw(featom *atom, regionhandle region); void poTextDraw(featom *atom, regionhandle region); fecallback poCallback[] = { {poClose, "PO_CloseObjectiveWindow"}, {NULL, NULL} }; fedrawcallback poDrawCallback[] = { {poTextDraw, "PO_TextDraw"}, {NULL, NULL} }; void fleetIntelligenceDestroy(FleetIntelligence *fleetIntelligence) { memFree(fleetIntelligence->description); listDeleteNode(&fleetIntelligence->node); } FleetIntelligence *fleetIntelligenceCreate(char *description, bool8 showOnce) { FleetIntelligence *fleetIntelligence; fleetIntelligence = memAlloc(sizeof(FleetIntelligence), "Fleet Intelligence", 0); fleetIntelligence->showOnce = showOnce; fleetIntelligence->showNow = TRUE; fleetIntelligence->description = memStringDupe(description); listAddNode(&poFleetIntelligence, &fleetIntelligence->node, (void*) fleetIntelligence); // ASSUMING THAT THIS IS TRUE ONLY WHILE IN THE GAME ALREADY AND NOT LOADING if (showOnce) { poCurFleetIntelligence = fleetIntelligence; poPlayerObjectivesBegin(ghMainRegion); fleetIntelligence = NULL; } return fleetIntelligence; } Objective *objectiveAndFleetIntelligenceCreate(char *label, char *briefDescription, char* fullDescription, bool8 showOnce, bool primary) { Objective *objective; bool hyperspace; if (objectiveFind(label)) { return NULL; } // allocate the node objective = memAlloc(sizeof(Objective), "objective", 0); objective->status = FALSE; objective->primary = primary; memStrncpy(objective->label, label, MAX_OBJECTIVE_LABEL_LENGTH); objective->description = memStringDupe(briefDescription); if (!_stricmp(label, "hyperspace")) { hyperspace = TRUE; singlePlayerGameInfo.playerCanHyperspace = TRUE; smUpdateHyperspaceStatus(TRUE); objective->fleetIntelligence = NULL; } else { hyperspace = FALSE; if (fullDescription != NULL) { objective->fleetIntelligence = fleetIntelligenceCreate(fullDescription, showOnce); } else { objective->fleetIntelligence = NULL; } } // keep track of all allocations if (!objectives) { objectives = memAlloc(sizeof(Objective*)*OBJECTIVES_ALLOC_INITIAL, "objectives", 0); objectivesAllocated = OBJECTIVES_ALLOC_INITIAL; objectivesUsed = 0; } if (objectivesUsed >= objectivesAllocated) { // allocate more if necessary objectives = memRealloc(objectives, sizeof(Objective*)*(objectivesAllocated + OBJECTIVES_ALLOC_INCREMENT), "objectives", 0); objectivesAllocated += OBJECTIVES_ALLOC_INCREMENT; } objectives[objectivesUsed++] = objective; if (hyperspace) { tbObjectivesHyperspace((ubyte*)objectives[objectivesUsed-1]); } else { tbObjectivesListAddItem((ubyte*)objectives[objectivesUsed-1]); } return objective; } void fleetIntelligenceDestroyAll(void) { FleetIntelligence *fleetIntelligence; udword numEntries; udword count; Node *node; numEntries = poFleetIntelligence.num; node = poFleetIntelligence.head; for (count = 0; count < numEntries; count++) { fleetIntelligence = (FleetIntelligence*) listGetStructOfNode(node); node = node->next; if (node != NULL && fleetIntelligence != NULL) { fleetIntelligenceDestroy(fleetIntelligence); } else break; } } void objectiveStartup(void) { objectives = NULL; objectivesAllocated = 0; objectivesUsed = 0; feCallbackAddMultiple(poCallback); //add in the callbacks listInit(&poFleetIntelligence); } void objectiveShutdown(void) { objectiveDestroyAll(); //fleetIntelligenceDestroyAll(); } // // Set status of an objective. // True == complete // False == not complete // void objectiveSet(char *label, sdword status) { Objective *obj = objectiveFind(label); sdword i = 0, completed = 0; if (!obj) return; obj->status = status; } // // Get status of an objective. // True == complete // False == not complete // sdword objectiveGet(char *label) { Objective *obj = objectiveFind(label); if (!obj) return FALSE; return obj->status; } // // Get status of all objectives. // True == all complete // False == not all complete // // note that with no objectives, this will return TRUE // sdword objectiveGetAll(void) { sdword i = 0; while (i < objectivesUsed) { if (!objectives[i]->status) return FALSE; ++i; } return TRUE; } // // remove one objective // void objectiveDestroy(char *label) { sdword i = 0; Objective *obj = NULL; while (i < objectivesUsed) { if (!strncmp(objectives[i]->label, label, MAX_OBJECTIVE_LABEL_LENGTH)) { obj = objectives[i]; break; } ++i; } if (!obj) return; tbObjectivesListRemoveItem((ubyte *)obj); if (obj->fleetIntelligence) { if (obj->fleetIntelligence == poCurFleetIntelligence) { poCurFleetIntelligence = NULL; } fleetIntelligenceDestroy(obj->fleetIntelligence); } if (obj->description) memFree(obj->description); memFree(obj); --objectivesUsed; if (i < objectivesUsed) memmove(&objectives[i], &objectives[i+1], sizeof(Objective*)*(objectivesUsed-i)); } // // Remove all objectives from a mission. // void objectiveDestroyAll(void) { sdword i = 0; Objective *obj; // ASSUMING THIS GETS CALLED AT THE END OF A MISSION tbObjectivesListCleanUp(); fleetIntelligenceDestroyAll(); while (i < objectivesUsed) { obj = objectives[i]; memFree(obj->description); memFree(obj); ++i; } objectivesUsed = 0; if (objectives) memFree(objectives); objectives = NULL; objectivesAllocated = 0; } // // finds an objective by label // // returns NULL if not found // Objective *objectiveFind(char *label) { sdword i = 0; while (i < objectivesUsed) { if (!strncmp(objectives[i]->label, label, MAX_OBJECTIVE_LABEL_LENGTH)) return objectives[i]; ++i; } return NULL; } // // this can be removed, NOW OBSOLETE (remove reference in MAINRGN.C) // void objectiveDrawStatus(void) { } /*----------------------------------------------------------------------------- Name : poPopupTextDraw Description : Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void poPopupTextDraw(rectangle *rect) { sdword x, y, width, rectWidth; // udword count; fonthandle currentFont; bool8 done, justified; char *pos, *oldpos; char oldline[256], line[256]; if (!gameIsRunning || nisIsRunning || (tutorial==TUTORIAL_ONLY)) return; rectWidth = (rect->x1 - rect->x0); poHeadingFont = frFontRegister(poHeadingFontName); poTextFont = frFontRegister(poTextFontName); //currentFont = fontMakeCurrent(poPopupFont); currentFont = fontMakeCurrent(poTextFont); if (poCurFleetIntelligence != NULL) { x = rect->x0; y = rect->y0; dbgAssert(poCurFleetIntelligence->description != NULL); pos = poCurFleetIntelligence->description; done = FALSE; while (!done) { justified = FALSE; line[0]=0; while (!justified) { strcpy(oldline, line); oldpos = pos; pos = getWord(line, pos); if (pos[0] == '\n') { justified = TRUE; pos++; while ( pos[0] == ' ' ) pos++; } else { if ( (width=fontWidth(line)) > rectWidth) { strcpy(line, oldline); pos = oldpos; while ( pos[0] == ' ' ) pos++; justified = TRUE; } if (pos[0]==0) { justified = TRUE; done = TRUE; } } } fontPrintf(x,y,OBJECTIVE_POPUPTEXT_COLOR,"%s",line); y += fontHeight(" "); if (y > rect->y1 + fontHeight(" ")) done=TRUE; } } fontMakeCurrent(currentFont); } /*----------------------------------------------------------------------------- Name : poPlayerObjectivesBegin Description : startup the mission objectives window Inputs : Outputs : Return : ----------------------------------------------------------------------------*/ void poPlayerObjectivesBegin(regionhandle region) { spMainScreen(); // make sure we're on main screen // disbale rendering of main screen - NOT! //mrRenderMainScreen = FALSE; // disable taskbar popup window tbDisable = TRUE; smSensorsDisable = TRUE; mrDisable(); universePause = TRUE; feDrawCallbackAddMultiple(poDrawCallback); poBaseRegion = feScreenStart(region, "Single_Player_Objective"); } /*----------------------------------------------------------------------------- Name : poPopupFleetIntelligence Description : Starts the fleet intel event for a given objective Inputs : objective - objective clicked on Outputs : Return : Note : Creates a KAS global variable with the name "G_CLICK_