📄 script.cpp
字号:
//
// 脚本(Script)的执行
//
// Copyright (c) 2000-2001 Chihiro.SAKAMOTO (HyperWorks)
//
#include "stdafx.h"
#include <stdlib.h>
#include "MainWin.h"
#include "File.h"
#include "Misc.h"
#include "Script.h"
//
// 构造函数
//
CScriptAction::CScriptAction(CMainWin *win, CAction *oldAction, int mode)
: CAction(win, oldAction), reader(0)
{
// 命令表格(command table)的初始化
cmd_table.insert(CmdTab("set", &CScriptAction::SetCmd));
cmd_table.insert(CmdTab("calc", &CScriptAction::SetCmd));
cmd_table.insert(CmdTab("text", &CScriptAction::TextCmd));
cmd_table.insert(CmdTab("goto", &CScriptAction::GotoCmd));
cmd_table.insert(CmdTab("if", &CScriptAction::IfCmd));
cmd_table.insert(CmdTab("menu", &CScriptAction::MenuCmd));
cmd_table.insert(CmdTab("exec", &CScriptAction::ExecCmd));
cmd_table.insert(CmdTab("load", &CScriptAction::LoadCmd));
cmd_table.insert(CmdTab("update", &CScriptAction::UpdateCmd));
cmd_table.insert(CmdTab("clear", &CScriptAction::ClearCmd));
cmd_table.insert(CmdTab("music", &CScriptAction::MusicCmd));
cmd_table.insert(CmdTab("stopm", &CScriptAction::StopmCmd));
cmd_table.insert(CmdTab("wait", &CScriptAction::WaitCmd));
cmd_table.insert(CmdTab("sound", &CScriptAction::SoundCmd));
cmd_table.insert(CmdTab("fadein", &CScriptAction::FadeInCmd));
cmd_table.insert(CmdTab("fadeout", &CScriptAction::FadeOutCmd));
cmd_table.insert(CmdTab("wipein", &CScriptAction::WipeInCmd));
cmd_table.insert(CmdTab("wipeout", &CScriptAction::WipeOutCmd));
cmd_table.insert(CmdTab("cutin", &CScriptAction::CutInCmd));
cmd_table.insert(CmdTab("cutout", &CScriptAction::CutOutCmd));
cmd_table.insert(CmdTab("whitein", &CScriptAction::WhiteInCmd));
cmd_table.insert(CmdTab("whiteout", &CScriptAction::WhiteOutCmd));
cmd_table.insert(CmdTab("flash", &CScriptAction::FlashCmd));
cmd_table.insert(CmdTab("shake", &CScriptAction::ShakeCmd));
cmd_table.insert(CmdTab("mode", &CScriptAction::ModeCmd));
cmd_table.insert(CmdTab("system", &CScriptAction::SystemCmd));
cmd_table.insert(CmdTab("battle", &CScriptAction::BattleCmd));
cmd_table.insert(CmdTab("end", &CScriptAction::EndCmd));
status = Continue;
Pressed = FALSE;
MenuSelect = -1;
PlayMode = mode;
delete reader;
reader = 0;
}
//
// 析构函数
//
CScriptAction::~CScriptAction()
{
delete reader;
}
//
// 错误事件的格式
//
char *__cdecl CScriptAction::Format(const char *fmt, ...)
{
static char tmp[256];
va_list args;
va_start(args, fmt);
_vsnprintf(tmp, sizeof(tmp), fmt, args);
va_end(args);
return tmp;
}
//
// 暂停
//
void CScriptAction::Pause()
{
switch (status) {
case WaitMenuDone: // 等待菜单
if (MenuSelect >= 0) {
Parent->SelectMenu(MenuSelect, false);
MenuSelect = -1;
}
break;
}
}
//
// 解除暂停
//
void CScriptAction::Resume()
{
switch (status) {
case WaitMenuDone: // 等待菜单
{
CPoint point;
GetCursorPos(&point);
Parent->ScreenToClient(&point);
MenuSelect = Parent->GetMenuSelect(point);
if (MenuSelect >= 0)
Parent->SelectMenu(MenuSelect, true);
}
break;
}
}
//
// 按下鼠标左键时的处理
//
void CScriptAction::LButtonDown(UINT modKeys, CPoint point)
{
switch (status) {
case WaitMenuDone: // 等待菜单
Pressed = TRUE;
break;
}
}
//
// 放开鼠标左键时的处理
//
void CScriptAction::LButtonUp(UINT modKeys, CPoint point)
{
switch (status) {
case WaitKeyPressed: // 等待按键
Parent->HideWaitMark();
status = Continue;
break;
case WaitMenuDone: // 等待菜单
if (Pressed) {
Pressed = FALSE;
MouseMove(modKeys, point);
if (MenuSelect >= 0) {
Parent->SetValue(MenuAnser, Parent->GetMenuAnser(MenuSelect));
Parent->HideMenuWindow();
status = Continue;
}
MenuSelect = -1;
}
break;
}
}
//
// 按下鼠标右键时的处理
//
void CScriptAction::RButtonDown(UINT modKeys, CPoint point)
{
switch (status) {
case WaitKeyPressed: // 等待按键
Parent->FlipMessageWindow();
break;
}
}
//
// 移动鼠标时的处理
//
void CScriptAction::MouseMove(UINT modKeys, CPoint point)
{
switch (status) {
case WaitMenuDone: // 等待菜单
{
int sel = Parent->GetMenuSelect(point);
if (sel != MenuSelect) {
Parent->SelectMenu(MenuSelect, false);
MenuSelect = sel;
Parent->SelectMenu(MenuSelect, true);
}
}
break;
}
}
//
// 按下键盘时的处理
//
void CScriptAction::KeyDown(UINT key)
{
switch (key) {
case VK_RETURN:
case VK_SPACE:
switch (status) {
case WaitKeyPressed: // 等待按键
Parent->HideWaitMark();
status = Continue;
break;
case WaitMenuDone: // 等待菜单
if (MenuSelect >= 0) {
Parent->SetValue(MenuAnser, Parent->GetMenuAnser(MenuSelect));
Parent->HideMenuWindow();
status = Continue;
MenuSelect = -1;
}
break;
}
break;
case VK_ESCAPE:
switch (status) {
case WaitKeyPressed: // 等待按键
Parent->FlipMessageWindow();
break;
}
break;
case VK_UP:
if (status == WaitMenuDone) { // 等待菜单
Parent->SelectMenu(MenuSelect, false);
MenuSelect--;
if (MenuSelect < 0)
MenuSelect = Parent->GetMenuItemCount() - 1;
Parent->SelectMenu(MenuSelect, true);
}
break;
case VK_DOWN:
if (status == WaitMenuDone) { // 等待菜单
Parent->SelectMenu(MenuSelect, false);
MenuSelect++;
if (MenuSelect >= Parent->GetMenuItemCount())
MenuSelect = 0;
Parent->SelectMenu(MenuSelect, true);
}
break;
}
}
//
// IDLE的处理
//
BOOL CScriptAction::IdleAction()
{
if (status == Continue) { // 执行“继续”
do {
status = Step(); // 执行一步
} while (status == Continue) ; // 继续吗?
if (status == BreakGame) { // 结束
Abort();
}
else if (status == WaitNextIdle) { // 等待下个IDLE处理
status = Continue; // 继续
return TRUE;
}
else if (status == WaitWipeDone) { // 等待特效结束
return TRUE; // IDLE继续
}
}
return FALSE;
}
//
// 计时器的处理
//
bool CScriptAction::TimedOut(int timerId)
{
switch (timerId) {
case CMainWin::TimerSleep: // 等待Timeout
if (status == WaitTimeOut)
status = Continue;
break;
}
return true;
}
//
// Wipe特效结束时的处理
//
void CScriptAction::WipeDone()
{
if (status == WaitWipeDone) // 等待特效结束
status = Continue;
}
//
// Wave播放结束时的处理
//
void CScriptAction::WaveDone()
{
if (status == WaitWaveDone) // 等待WAVE播放结束
status = Continue;
}
//
// Script执行结束
//
void CScriptAction::Abort()
{
if (status == WaitMenuDone) // 如果要等待菜单的话
Parent->HideMenuWindow(); // 关闭菜单
Parent->HideMessageWindow(); // 关闭事件
status = BreakGame;
delete reader; // 删除Script
reader = 0;
Parent->ScriptDone();
}
//
// 读取Script档
//
bool CScriptAction::LoadFile(const char *name)
{
char path[_MAX_PATH];
sprintf(path, SCRIPTPATH "%s.txt", name);
label_table.clear(); // 清除标签表(lable table)
delete reader; // 丢弃之前的Script
reader = new TextReader(path);
return reader->IsOk();
}
//
// 读取Script档,并设定成员变量
//
BOOL CScriptAction::Load(const char *name)
{
strncpy(Parent->GetParam().last_script, name, 16);
if (!LoadFile(name)) {
Parent->MessageBox(Format("无法读取 [%s] Script档案", name));
return FALSE;
}
return TRUE;
}
//
// 进行设定,让Script从储存位置中可以再度开启
//
BOOL CScriptAction::Setup(CParams ¶m)
{
reader->SetPosition(param.script_pos);
if (param.last_bgm)
Parent->StartMusic(param.last_bgm);
switch (param.show_flag) {
case SHOWCG_IMAGE:
if (param.last_bg[0])
LoadGraphic(param.last_bg, POSITION_BACK);
if (param.last_overlap[0]) {
LoadGraphic(param.last_overlap, POSITION_OVERLAP);
}
Parent->WipeIn();
status = WaitWipeDone;
break;
case SHOWCG_BLACKNESS:
Parent->CutOut();
status = Continue;
break;
case SHOWCG_WHITENESS:
Parent->CutOut(TRUE);
status = Continue;
break;
}
return TRUE;
}
//
// 错误事件的输出
//
void __cdecl CScriptAction::Error(const char *fmt, ...)
{
va_list args;
char str[256];
int len = 0;
if (reader)
len = sprintf(str, "%s:%d ", reader->GetFileName(), reader->GetLineNo());
va_start(args, fmt);
_vsnprintf(str + len, sizeof(str) - len, fmt, args);
va_end(args);
Parent->MessageBox(str);
}
//
// 比对关键字
//
bool CScriptAction::ChkKeyword(const char *str, const char *keyword)
{
while (*str) {
if (tolower(*str++) != *keyword++)
return false;
}
return true;
}
//
// CG的指定位置设定成位置码
//
int CScriptAction::GetPosition(const char *str)
{
if (ChkKeyword(str, "bg") || ChkKeyword(str, "back"))
return POSITION_BACK;
if (ChkKeyword(str, "bgo") || ChkKeyword(str, "backonly"))
return POSITION_BACKONLY;
if (ChkKeyword(str, "overlap"))
return POSITION_OVERLAP;
Error("文法错误(position)");
return POSITION_BACK;
}
//
// 依照命令来更新指定特效
//
int CScriptAction::GetUpdateType(const char *str)
{
if (ChkKeyword(str, "cut") || ChkKeyword(str, "now"))
return UPDATE_NOW;
if (ChkKeyword(str, "overlap"))
return UPDATE_OVERLAP;
if (ChkKeyword(str, "wipe"))
return UPDATE_WIPE;
Error("文法错误(update type)");
return UPDATE_NOW;
}
//
// 移到Script中指定的位置
//
int CScriptAction::GotoCommand(const char *label)
{
labelmap::iterator p = label_table.find(label);
if (p == label_table.end()) { // 找不到标签
const char *str;
// 从Script档中搜寻标签
while ((str = reader->GetString()) != NULL) {
Lexer lexer(str);
if (lexer.NumToken() == 1
&& lexer.GetType() == Lexer::IsLabel) {
if (SetLabel(lexer) != Continue) // 登录标签
return BreakGame;
const char *p = lexer.GetString(0) + 1;
if (stricmp(p, label) == 0) // 找到标签了!
return Continue;
}
}
Error("找不到标签[%s]", label);
return BreakGame;
}
reader->SetPosition(p->second);
return Continue;
}
//
// 标签的登录指令
//
int CScriptAction::SetLabel(Lexer &lexer)
{
if (lexer.NumToken() != 1) {
Error("参数太多了");
return BreakGame;
}
const char *label = lexer.GetString() + 1;
labelmap::iterator p = label_table.find(label);
if (p != label_table.end()) { // 标签已经存在
if (label_table[label] != reader->GetPosition()) {
Error("标签 [%s] 已经登录过了", label);
return BreakGame;
}
}
label_table[label] = reader->GetPosition();
return Continue;
}
//
// set指令
//
int CScriptAction::SetCmd(Lexer &lexer)
{
const char *name = lexer.GetString();
const char *op = lexer.GetString();
int value;
bool b = lexer.GetValue(&value);
if (name == 0 || op == 0 || !b || lexer.GetString() != 0) {
Error("文法错误");
return BreakGame;
}
if (strcmp(op, "=") == 0) { // 指定代入
Parent->SetValue(name, value);
}
else if (strcmp(op, "+") == 0) { // 加法
Parent->AddValue(name, value);
}
else if (strcmp(op, "-") == 0) { // 减法
Parent->DelValue(name, value);
}
else {
Error("文法错误");
return BreakGame;
}
return Continue;
}
//
// goto指令
//
int CScriptAction::GotoCmd(Lexer &lexer)
{
const char *label = lexer.GetString();
if (label == 0 || lexer.GetString() != 0) {
Error("文法错误(in goto command)");
return BreakGame;
}
return GotoCommand(label);
}
//
// 取得变量或常数
//
bool CScriptAction::GetValue(Lexer &lexer, int *value)
{
if (lexer.GetType() == Lexer::IsString) { // 字符串
const char *name = lexer.GetString();
*value = Parent->GetValue(name);
return true;
}
return lexer.GetValue(value); // 当成数字读看看
}
//
// if 指令
//
int CScriptAction::IfCmd(Lexer &lexer)
{
int value1, value2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -