mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
FREESCAPE: implemented timed condition executions from dark (and other games)
This commit is contained in:
parent
b13065da36
commit
77728fcf73
@ -526,7 +526,7 @@ bool FreescapeEngine::onScreenControls(Common::Point mouse) {
|
|||||||
|
|
||||||
void FreescapeEngine::executeMovementConditions() {
|
void FreescapeEngine::executeMovementConditions() {
|
||||||
// Only execute "on collision" room/global conditions
|
// Only execute "on collision" room/global conditions
|
||||||
executeLocalGlobalConditions(false, true);
|
executeLocalGlobalConditions(false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreescapeEngine::updateTimeVariables() {
|
void FreescapeEngine::updateTimeVariables() {
|
||||||
@ -537,7 +537,7 @@ void FreescapeEngine::updateTimeVariables() {
|
|||||||
_lastMinute = minutes;
|
_lastMinute = minutes;
|
||||||
_gameStateVars[0x1e] += 1;
|
_gameStateVars[0x1e] += 1;
|
||||||
_gameStateVars[0x1f] += 1;
|
_gameStateVars[0x1f] += 1;
|
||||||
executeLocalGlobalConditions(false, true); // Only execute "on collision" room/global conditions
|
executeLocalGlobalConditions(false, true, false); // Only execute "on collision" room/global conditions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,8 +276,8 @@ public:
|
|||||||
Math::Vector3d _objExecutingCodeSize;
|
Math::Vector3d _objExecutingCodeSize;
|
||||||
virtual void executeMovementConditions();
|
virtual void executeMovementConditions();
|
||||||
void executeObjectConditions(GeometricObject *obj, bool shot, bool collided);
|
void executeObjectConditions(GeometricObject *obj, bool shot, bool collided);
|
||||||
void executeLocalGlobalConditions(bool shot, bool collided);
|
void executeLocalGlobalConditions(bool shot, bool collided, bool timer);
|
||||||
void executeCode(FCLInstructionVector &code, bool shot, bool collided);
|
void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
void executeIncrementVariable(FCLInstruction &instruction);
|
void executeIncrementVariable(FCLInstruction &instruction);
|
||||||
@ -531,7 +531,6 @@ public:
|
|||||||
|
|
||||||
int _lastTenSeconds;
|
int _lastTenSeconds;
|
||||||
void updateTimeVariables() override;
|
void updateTimeVariables() override;
|
||||||
void executeMovementConditions() override;
|
|
||||||
|
|
||||||
void drawDOSUI(Graphics::Surface *surface) override;
|
void drawDOSUI(Graphics::Surface *surface) override;
|
||||||
void drawFullscreenMessage(Common::String message);
|
void drawFullscreenMessage(Common::String message);
|
||||||
|
@ -201,27 +201,20 @@ void DarkEngine::checkIfStillInArea() {
|
|||||||
FreescapeEngine::checkIfStillInArea();
|
FreescapeEngine::checkIfStillInArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DarkEngine::executeMovementConditions() {
|
|
||||||
// Only execute "on collision" room/global conditions
|
|
||||||
if (_currentArea->getAreaFlags() == 1)
|
|
||||||
executeLocalGlobalConditions(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DarkEngine::updateTimeVariables() {
|
void DarkEngine::updateTimeVariables() {
|
||||||
// This function only executes "on collision" room/global conditions
|
// This function only executes "on collision" room/global conditions
|
||||||
int seconds, minutes, hours;
|
int seconds, minutes, hours;
|
||||||
getTimeFromCountdown(seconds, minutes, hours);
|
getTimeFromCountdown(seconds, minutes, hours);
|
||||||
if (_lastTenSeconds != seconds / 10) {
|
if (_lastTenSeconds != seconds / 10) {
|
||||||
_lastTenSeconds = seconds / 10;
|
_lastTenSeconds = seconds / 10;
|
||||||
if (_currentArea->getAreaFlags() == 0)
|
executeLocalGlobalConditions(false, false, true);
|
||||||
executeLocalGlobalConditions(false, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lastMinute != minutes) {
|
if (_lastMinute != minutes) {
|
||||||
_lastMinute = minutes;
|
_lastMinute = minutes;
|
||||||
_gameStateVars[0x1e] += 1;
|
_gameStateVars[0x1e] += 1;
|
||||||
_gameStateVars[0x1f] += 1;
|
_gameStateVars[0x1f] += 1;
|
||||||
executeLocalGlobalConditions(false, true);
|
executeLocalGlobalConditions(false, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
|
|||||||
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
|
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
|
||||||
|
|
||||||
// on the 8bit platforms, all instructions have a conditional flag;
|
// on the 8bit platforms, all instructions have a conditional flag;
|
||||||
// we'll want to convert them into runs of "if shot? then" and "if collided? then",
|
// we'll want to convert them into runs of "if shot? then", "if collided? then" or "if timer? then",
|
||||||
// and we'll want to start that from the top
|
// and we'll want to start that from the top
|
||||||
uint8 conditionalIsShot = 0x1;
|
|
||||||
FCLInstructionVector *conditionalInstructions = new FCLInstructionVector();
|
FCLInstructionVector *conditionalInstructions = new FCLInstructionVector();
|
||||||
FCLInstruction currentInstruction;
|
FCLInstruction currentInstruction;
|
||||||
|
|
||||||
@ -55,30 +54,42 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
|
|||||||
0, 0, 0, 0, 0, 0, 2, 2,
|
0, 0, 0, 0, 0, 0, 2, 2,
|
||||||
1};
|
1};
|
||||||
|
|
||||||
|
detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
|
||||||
|
Token::Type newConditional;
|
||||||
|
Token::Type oldConditional;
|
||||||
|
|
||||||
while (bytePointer < sizeOfTokenisedContent) {
|
while (bytePointer < sizeOfTokenisedContent) {
|
||||||
// get the conditional type of the next operation
|
// get the conditional type of the next operation
|
||||||
uint8 newConditionalIsShot = tokenisedCondition[bytePointer] & 0x80;
|
uint8 conditionalByte = tokenisedCondition[bytePointer];
|
||||||
|
|
||||||
|
if (conditionalByte & 0x80)
|
||||||
|
newConditional = Token::SHOTQ;
|
||||||
|
else if (conditionalByte & 0x40)
|
||||||
|
newConditional = Token::TIMERQ;
|
||||||
|
else
|
||||||
|
newConditional = Token::COLLIDEDQ;
|
||||||
|
|
||||||
// if the conditional type has changed then end the old conditional,
|
// if the conditional type has changed then end the old conditional,
|
||||||
// if we were in one, and begin a new one
|
// if we were in one, and begin a new one
|
||||||
if (newConditionalIsShot != conditionalIsShot) {
|
if (bytePointer == 0 || newConditional != oldConditional) {
|
||||||
|
oldConditional = newConditional;
|
||||||
FCLInstruction branch;
|
FCLInstruction branch;
|
||||||
if (conditionalIsShot)
|
branch = FCLInstruction(oldConditional);
|
||||||
branch = FCLInstruction(Token::SHOTQ);
|
|
||||||
else
|
|
||||||
branch = FCLInstruction(Token::COLLIDEDQ);
|
|
||||||
|
|
||||||
branch.setBranches(conditionalInstructions, nullptr);
|
branch.setBranches(conditionalInstructions, nullptr);
|
||||||
instructions.push_back(branch);
|
instructions.push_back(branch);
|
||||||
|
|
||||||
conditionalIsShot = newConditionalIsShot;
|
if (bytePointer > 0)
|
||||||
if (bytePointer)
|
|
||||||
detokenisedStream += "ENDIF\n";
|
detokenisedStream += "ENDIF\n";
|
||||||
|
|
||||||
if (conditionalIsShot)
|
if (oldConditional == Token::SHOTQ)
|
||||||
detokenisedStream += "IF SHOT? THEN\n";
|
detokenisedStream += "IF SHOT? THEN\n";
|
||||||
else
|
else if (oldConditional == Token::TIMERQ)
|
||||||
|
detokenisedStream += "IF TIMER? THEN\n";
|
||||||
|
else if (oldConditional == Token::COLLIDEDQ)
|
||||||
detokenisedStream += "IF COLLIDED? THEN\n";
|
detokenisedStream += "IF COLLIDED? THEN\n";
|
||||||
|
else
|
||||||
|
error("Invalid conditional: %x", oldConditional);
|
||||||
|
|
||||||
// Allocate the next vector of instructions
|
// Allocate the next vector of instructions
|
||||||
conditionalInstructions = new FCLInstructionVector();
|
conditionalInstructions = new FCLInstructionVector();
|
||||||
@ -415,10 +426,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
|
|||||||
// conditionalInstructions->push_back(currentInstruction);
|
// conditionalInstructions->push_back(currentInstruction);
|
||||||
|
|
||||||
FCLInstruction branch;
|
FCLInstruction branch;
|
||||||
if (conditionalIsShot)
|
branch = FCLInstruction(oldConditional);
|
||||||
branch = FCLInstruction(Token::SHOTQ);
|
|
||||||
else
|
|
||||||
branch = FCLInstruction(Token::COLLIDEDQ);
|
|
||||||
|
|
||||||
branch.setBranches(conditionalInstructions, nullptr);
|
branch.setBranches(conditionalInstructions, nullptr);
|
||||||
instructions.push_back(branch);
|
instructions.push_back(branch);
|
||||||
|
@ -72,11 +72,11 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
|
|||||||
_firstSound = true;
|
_firstSound = true;
|
||||||
_objExecutingCodeSize = obj->getSize();
|
_objExecutingCodeSize = obj->getSize();
|
||||||
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
|
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
|
||||||
executeCode(obj->_condition, shot, collided);
|
executeCode(obj->_condition, shot, collided, false); // TODO: check this last parameter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided) {
|
void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided, bool timer) {
|
||||||
if (isCastle())
|
if (isCastle())
|
||||||
return;
|
return;
|
||||||
debugC(1, kFreescapeDebugCode, "Executing room conditions");
|
debugC(1, kFreescapeDebugCode, "Executing room conditions");
|
||||||
@ -85,17 +85,17 @@ void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided) {
|
|||||||
|
|
||||||
for (uint i = 0; i < conditions.size(); i++) {
|
for (uint i = 0; i < conditions.size(); i++) {
|
||||||
debugC(1, kFreescapeDebugCode, "%s", conditionSources[i].c_str());
|
debugC(1, kFreescapeDebugCode, "%s", conditionSources[i].c_str());
|
||||||
executeCode(conditions[i], shot, collided);
|
executeCode(conditions[i], shot, collided, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugC(1, kFreescapeDebugCode, "Executing global conditions (%d)", _conditions.size());
|
debugC(1, kFreescapeDebugCode, "Executing global conditions (%d)", _conditions.size());
|
||||||
for (uint i = 0; i < _conditions.size(); i++) {
|
for (uint i = 0; i < _conditions.size(); i++) {
|
||||||
debugC(1, kFreescapeDebugCode, "%s", _conditionSources[i].c_str());
|
debugC(1, kFreescapeDebugCode, "%s", _conditionSources[i].c_str());
|
||||||
executeCode(_conditions[i], shot, collided);
|
executeCode(_conditions[i], shot, collided, timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided) {
|
void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer) {
|
||||||
assert(!(shot && collided));
|
assert(!(shot && collided));
|
||||||
int ip = 0;
|
int ip = 0;
|
||||||
int codeSize = code.size();
|
int codeSize = code.size();
|
||||||
@ -109,13 +109,19 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
|
|||||||
break;
|
break;
|
||||||
case Token::COLLIDEDQ:
|
case Token::COLLIDEDQ:
|
||||||
if (collided)
|
if (collided)
|
||||||
executeCode(*instruction._thenInstructions, shot, collided);
|
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||||
// else branch is always empty
|
// else branch is always empty
|
||||||
assert(instruction._elseInstructions == nullptr);
|
assert(instruction._elseInstructions == nullptr);
|
||||||
break;
|
break;
|
||||||
case Token::SHOTQ:
|
case Token::SHOTQ:
|
||||||
if (shot)
|
if (shot)
|
||||||
executeCode(*instruction._thenInstructions, shot, collided);
|
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||||
|
// else branch is always empty
|
||||||
|
assert(instruction._elseInstructions == nullptr);
|
||||||
|
break;
|
||||||
|
case Token::TIMERQ:
|
||||||
|
if (timer)
|
||||||
|
executeCode(*instruction._thenInstructions, shot, collided, timer);
|
||||||
// else branch is always empty
|
// else branch is always empty
|
||||||
assert(instruction._elseInstructions == nullptr);
|
assert(instruction._elseInstructions == nullptr);
|
||||||
break;
|
break;
|
||||||
|
@ -92,7 +92,7 @@ void FreescapeEngine::shoot() {
|
|||||||
|
|
||||||
executeObjectConditions(gobj, true, false);
|
executeObjectConditions(gobj, true, false);
|
||||||
}
|
}
|
||||||
executeLocalGlobalConditions(true, false); // Only execute "on shot" room/global conditions
|
executeLocalGlobalConditions(true, false, false); // Only execute "on shot" room/global conditions
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreescapeEngine::changePlayerHeight(int index) {
|
void FreescapeEngine::changePlayerHeight(int index) {
|
||||||
|
Loading…
Reference in New Issue
Block a user