GOALS
My goals in creating a mission architecture are as follows:
Encapsulation: I would like to create a "mission type" that entirely implements a mission. This would make it easier to add new missions without disturbing other missions. [To understand why this is hard today, think of how you would implement a mission to destroy an enemy ship. You need an event on the mission giver (the station giving the mission) to detect when the target is destroyed. But if you want to add a new mission to destroy a different enemy, you would have to modify the same event (making sure to test for which mission is currently active). I propose having each mission implemented by its own type; thus the event would be on the mission itself.]
Mission/Trigger Separation: It is common today to have the station that gives (triggers) the mission to also be the object that implements the mission. This means that if you want to add a new mission, you have to override the entire object. By separating missions into their own type we can break this connection. The implementation of a station should not know what missions it can give. Instead, it should enumerate appropriate missions with typFind (or something). This would allow, for example, mods to add new Commonwealth Fleet missions without having to override an entire CSC.
Standard Mission Interface: Because each mission is implemented separately, there is no way to determine (in a generic way) which missions the player has accepted. I propose adding functions to enumerate and manipulate the set of open and completed missions. This would allow the UI to show this information to the player; it would also allow mods to use this information.
Cross-System Missions: Finally, I propose that missions should be accessible across systems. At minimum this allows for a mission to properly handle the player leaving the system and returning. It also allows multi-system missions. [For example, a mission could require the player to travel to n different systems and destroy m different enemies.]
PROPOSED IMPLEMENTATION
In order to achieve the above goals, I propose the following concepts:
MissionType
A MissionType is a new design type that defines a type of mission. It is the encapsulation object that implements everything about the mission. For example, imagine something like:
Code: Select all
<MissionType UNID="..."
name="Destroy Sung station mission"
attributes="commonwealthMilitia"
>
<Events>
<OnCreate>
; generate a random mission. E.g., pick a random Sung station to destroy in
; the current system.
; gMission is the mission object (use it to store mission details)
; gSource is the object giving the mission.
; Returns Nil if mission could not be created.
</OnCreate>
<OnMissionAccepted>
; Player accepted mission.
</OnMissionAccepted>
<OnObjDestroyed>
; If obj destroyed is the target, then mission accomplished.
; Call msnSuccess
</OnObjDestroyed>
</Events>
<Language>
<Text id="MissionBrief">
; Return string describing the mission
; gMission is mission object
; gSource is object giving the mission (e.g., station)
</Text>
</Language>
</MissionType>
A mission object represents a mission that has been created. Some of these mission objects have been accepted by the player (and are thus "active"). Others are available but have not been accepted (these are "open" missions).
A station that wants to give missions can create a mission as follows:
(msnCreate {unid})
Where "unid" is the UNID of the mission. Note that the station could have randomly chosen a mission using typFind. msnCreate returns a mission object, which can be manipulated.
The station can describe the mission to the player as follows:
(msnTranslate gMission 'MissionBrief)
If the player accepts the mission, the station can call:
(msnAccept gMission)
The above will start the mission (calling OnMissionAccepted).
At any time an object may call
(msnGetProperty gMission 'status)
To get the status of the mission. The result is one of the following:
'open -> mission has not been accepted or rejected by the player
'active -> mission has been accepted by the player and is in progress
'rejected -> mission has been rejected by the player
'success -> mission has been completed successfully
'failure -> mission has failed
To control when a player completes a mission, script may call:
(msnSuccess gMission)
or
(msnFailure gMission)
You may get the list of missions as follows:
(msnGetMissions criteria) -> list of mission objects
The above is a very rough description of my proposal. I haven't yet begun implementation, so the eventual design might differ. I would love to hear feedback.