⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 script.cpp

📁 圣剑二完整的游戏代码。附作者写的三篇文章。游戏的开发过程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}

//提行
int CScript::GotoNextLine(int lp)
{
	if( lp== -1 ) 
		lp=Point;

	for(int i=lp; i<DataLen; i++)
	{
		if( Data[i]=='\n' )	//是回车
		{
			Point=i+1;			//移动到回车的下一个字符
			return Point-lp;	//返回偏移量	
		}
	}

	Point=i;					//没有找到回车,移动到末尾
	return Point-lp;
}

//转移到指定位置
int CScript::Goto(char *index)
{
	int lp=Point;	//现场	保存
	Point=0;		//回到开头
	char *CmdStr;
	while(1)
	{
		CmdStr=ReadCommand();	//从开头起循环读一条指令
		if( CmdStr[strlen(CmdStr)-1] == ':' )	//是标号加上一个':'
		{
			CmdStr[strlen(CmdStr)-1] = 0;		//将它变成标号,不要后面的 :
			if( strcmp( CmdStr, index ) == 0 )	//是我们想要跳转的标号
			{
				_FREE(CmdStr);
				return Point;					//返回位置
			}
		}
		
		if( Point >= DataLen-1 )				//没有找到
		{
			ShowMessage("Prompt <%s> in file %s is not found!", index, FileName);
			Point=lp;
			_FREE(CmdStr);
			return 0;
		}
	}
	_FREE(CmdStr);
}

//运行一段脚本
CScript::SCRIPTRETURN CScript::Run(char *filename, char *index, int iPoint)
{
	char *CmdStr;
	char *CmdName;

	//递归层次
	strcpy( RecursionFile[RecursionLevel], filename );

	if( Open(filename) )		//打开文件
	{
		Point=iPoint;			//移动到要开始执行的地方
		if( index != "" ) 
			Goto(index);		//如果指定了开始执行的标号,就跳转到该位置

		while(1)
		{
			CmdStr=ReadCommand();			//读一条指令
			CmdName=GetCommandName(CmdStr);	//获取指令名称

			if( CmdStr[strlen(CmdStr)-1] == ':' )//是标号
			{
				_FREE( CmdName );
				_FREE( CmdStr );
				continue;
			}

			//暂时挂起脚本
			if( stricmp( CmdStr, "break" ) == 0 )	//是break就挂起
			{
				RecursionPoint[RecursionLevel]=Point;	//保存断点
				Message.PutMessage(MSG_BREAKSCRIPT, Point, 0, 0, NULL);//放入一个消息
				_FREE( CmdName );
				_FREE( CmdStr );
				return SR_RECURSION;		//表示在递归,挂起
			}

			//没有指令,或者是return 就返回
			else if( stricmp( CmdStr, "return" ) == 0 || CmdStr==NULL )	
			{
				_FREE( CmdName );
				_FREE( CmdStr );
				if( RecursionLevel >0 )		//在递归中
				{
					RecursionLevel--;		//返回上一级
				}
				return SR_OK;
			}

			//调用其它脚本(递归调用)
			else if( stricmp( CmdName, "call" ) == 0 )
			{
				RecursionPoint[RecursionLevel]=Point;	//保存断点
				RecursionLevel++;				//级数加一
	
				CScript SubScript;				//调用的脚本
				char *str=GetStringParam(CmdStr, 0);	//得到脚本名字(第一个参数)
				if( SubScript.Run( str ) == SR_RECURSION )	//挂起
				{
					_FREE(str);
					_FREE( CmdName );
					_FREE( CmdStr );
					return SR_RECURSION;				//挂起
				}
				_FREE(str);
				goto _Next3;							//继续执行
			}
_Next3:
			RunCommand(CmdStr);		//执行
			_FREE( CmdName );
			_FREE( CmdStr );
		}
	}
	_FREE( CmdName );
	_FREE( CmdStr );

	return SR_ERROR;				//应该是以return的方式结束的,所以返回错误
}

//运行一条语句
bool CScript::RunCommand(char *CmdStr)
{
	char *str1=NULL, *str2=NULL, *str3=NULL;
	int CommandId=-1;
	char *Cmd=GetCommandName(CmdStr);		//得到指令名字
	
	if( CmdStr == NULL || Cmd == NULL ) 
		return false;

	for(int i=0; i<MAX_COMMAND; i++)
	{
		if( stricmp(Cmd, COMMAND[i].Name)==0 )		//找到该指令
		{
			CommandId=i;
			free(Cmd);
			goto _Next;
		}
	}
	ShowMessage("Command [%s] is not define!", Cmd);
	free(Cmd);
	free(CmdStr);
	return false;

_Next:
	switch( COMMAND[CommandId].Id )
	{
	case 10:		//Goto	一个参数  
		{			//例如:goto("tiamo");
			char *str=GetStringParam(CmdStr, 0);
			Goto( str );
			free(str);
		}
		break;

	case 11:		//if	一个int型接一个分隔符接一个int型接一个分隔符接一个string型
		{			//例如:if($Process=1,"tiamo")
			int tmp1=GetIntParam(CmdStr, 0);
			int tmp2=GetIntParam(CmdStr, 1);
			char oper=GetOperation(CmdStr, 0);
			char *str=GetStringParam(CmdStr, 2);
			switch( oper )
			{
			case ',':
			case '=':
				if( tmp1==tmp2 )		//if($process=1,"tiamo")表示如果$process等于1的话
					Goto(str);			//跳转到标号叫tiamo的地方执行
				break;

			case '>':					//大于就跳转
				if( tmp1>tmp2 )
					Goto(str);
				break;

			case '<':					//小于就跳转
				if( tmp1<tmp2 )
					Goto(str);
				break;

			case '!':					//不等于就跳转
				if( tmp1 != tmp2 )
					Goto(str);
				break;
			}
			free(str);
		}
		break;

	case 16:		//set	设置全局变量的值,两个参数,一个全局变量,一个int变量
		{			//例如:set($tiamo,1);
			char *var=GetVariableParam(CmdStr, 0);
			SetValue(var, GetIntParam(CmdStr, 1));
			free(var);
		}
		break;

	case 17:		//add 改变全局变量的值,两个参数,一个全局变量,一个int变量
		{			//例如:add($tiamo,1); 让$tiamo的值加1
			char *var=GetVariableParam(CmdStr, 0);
			AddValue(var, GetIntParam(CmdStr, 1));
			free(var);
		}
		break;

	case 18:		//random 产生随机数,两个参数,一个全局变量,一个int变量
		{			//例如:random($tiamo,100);产生一个100以内的随机数并赋值给$tiamo
			random(1);
			int num=GetIntParam(CmdStr, 1);
			int ran=random( num );
			char *var=GetVariableParam(CmdStr, 0);
			SetValue(var, ran);
			free(var);
		}
		break;

	case 19:		//RGB合成三原色	四个参数,一个全局变量,三个int变量
		{			//例如:RGB($tiamo,0,0,0);让$tiamo变成黑色的RGB值
			int r=GetIntParam(CmdStr, 1);
			int g=GetIntParam(CmdStr, 2);
			int b=GetIntParam(CmdStr, 3);
			char *var=GetVariableParam(CmdStr, 0);
			SetValue(var, RGB(r, g, b));
			free(var);
		}
		break;

	//----------------------PutMessage--------------------------//

	case 20:		//SetPlayState	一个int参数:0 (挂起游戏,这时游戏脚本连续执行) 
					//						  1 (打开游戏,脚本单步执行)
		Message.PutMessage( MSG_SETPLAYSTATE, GetIntParam(CmdStr, 0), 0, 0, NULL);
		break;

	case 21:		//SetDisplayState	一个int参数:0 (白天) ;1 (夜晚)
		Message.PutMessage( MSG_SETDISPLAYSTATE, GetIntParam(CmdStr, 0), 0, 0, NULL);
		break;

	case 22:		//BackToTitle	没有参数,返回开始画面
		Message.PutMessage( MSG_BACKTOTITLE );
		break;

	case 23:		//TextTitle	两个string参数,filename,index,显示一段文字
		str1 = GetStringParam(CmdStr, 0);
		str2 = GetStringParam(CmdStr, 1);
		Message.PutMessage( MSG_TEXTTITLE, 0, 0, 0, str1, str2);
		break;

	case 24:		//Fight	三个string参数接三个int参数,打斗
		str1 = GetStringParam(CmdStr, 0);
		str2 = GetStringParam(CmdStr, 1);
		str3 = GetStringParam(CmdStr, 2);
		Message.PutMessage( MSG_FIGHT, GetIntParam(CmdStr, 3), GetIntParam(CmdStr, 4), 
			GetIntParam(CmdStr, 5), str1, str2, str3);
		break;

	case 25:		//EnableFight	一个int参数,是否踩地雷
		Message.PutMessage( MSG_ENABLEFIGHT, GetIntParam(CmdStr, 0));
		break;

	case 26:		//BossFight     一个int参数,是否是boss战
		Message.PutMessage( MSG_BOSSFIGHT, GetIntParam(CmdStr,0));
		break;

	case 29:		//LoadMap		一个string参数,地图文件名
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_LOADMAP, 0, 0, 0, str1);
		break;

	case 30:		//SaveMap		一个string参数,地图文件名
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SAVEMAP, 0, 0, 0, str1);
		break;

	case 31:		//AddMapHook	三个参数,两个int表示坐标,接一个string表示脚本文件
		str1 = GetStringParam(CmdStr, 2);
		Message.PutMessage( MSG_ADDMAPHOOK, GetIntParam(CmdStr, 0), 
			GetIntParam(CmdStr, 1), 0, str1);
		break;

	case 32:		//SetMapHook	三个int参数,坐标两个接一个陷阱的id
		Message.PutMessage( MSG_SETMAPHOOK, GetIntParam(CmdStr, 0), GetIntParam(CmdStr, 1), 
						GetIntParam(CmdStr, 2), NULL);
		break;

	case 33:		//SetMapCell	五个int参数,设置地图level(1)层的(x,y)点(2和3)为
					//								第page页(4)的第num号(5)元素
		Message.PutMessage( MSG_SETMAPCELL, GetIntParam(CmdStr, 0), GetIntParam(CmdStr, 1), 
					GetIntParam(CmdStr, 2), (char *)GetIntParam(CmdStr,3), 
					(char *)GetIntParam(CmdStr,4));
		break;

	case 34:		//SetMapBlock	三个int参数,坐标接阻挡关系
		Message.PutMessage( MSG_SETMAPBLOCK, GetIntParam(CmdStr, 0), GetIntParam(CmdStr, 1),
					GetIntParam(CmdStr, 2) );
		break;

	case 35:		//SetMapLevel	四个int参数,设置地图(x,y)点(1和2)的阻挡关系
					//							为level1\level2(3和4)
		Message.PutMessage( MSG_SETMAPLEVEL, GetIntParam(CmdStr, 0), GetIntParam(CmdStr, 1),
			GetIntParam(CmdStr, 2), (char *)GetIntParam(CmdStr,3), 
			(char *)GetIntParam(CmdStr,4));
		break;
		
	case 40:		//CenterMap		两个int(坐标)参数,以x,y为地图中心点
		Message.PutMessage( MSG_CENTERMAP, GetIntParam(CmdStr, 0), GetIntParam(CmdStr,1) );
		break;

	case 41:		//ScrollMapTo	三个int参数,两个坐标跟一个速度,卷动地图到x,y点(1和2)
		Message.PutMessage( MSG_SCROLLMAPTO, GetIntParam(CmdStr,0), GetIntParam(CmdStr,1), 
			GetIntParam(CmdStr,2) );
		break;

	case 50:		//LoadNpc		一个string参数,加载一个NPC文件
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_LOADNPC, 0,0,0, str1);
		break;

	case 60:
		Message.PutMessage(MSG_SETCPTYPE,GetIntParam(CmdStr,0),GetIntParam(CmdStr,1)
							,GetIntParam(CmdStr,2));
		break;

	case 100:		//MoveTo		两个int参数,强制主角走动到x,y点
		Message.PutMessage( MSG_MOVE, GetIntParam(CmdStr,0), GetIntParam(CmdStr, 1) ,0, NULL);
		break;

	case 101:		//SetPlayerDir	一个int参数,设置主角的方向,0=下 1=左 2=上 3=右
		Message.PutMessage( MSG_SETDIR, GetIntParam(CmdStr,0), 0 ,0, NULL);
		break;

	case 102:		//SetPlayerPos	三个int参数,设置主角的位置前两个是坐标,后一个不是必须
					//							表示是否清除原位置的地图阻挡,只要有,就清除
		Message.PutMessage( MSG_SETPOSITION, GetIntParam(CmdStr,0), GetIntParam(CmdStr,1) ,
					GetIntParam(CmdStr,2), NULL);
		break;

	case 103:		//CenterPlayer	没有参数,以主角为地图中心
		Message.PutMessage( MSG_CENTERPLAYER );
		break;

	case 104:		//SetPlayerShow	一个int参数		是否显示主角,1:是,0否
		Message.PutMessage( MSG_SETPLAYERSHOW, GetIntParam(CmdStr,0));
		break;

	case 110:		//LoadPlayer	三个参数,一个int表示角色编号,接两个string表示
					//						 ini文件和index索引,从ini文件读入主角
		str1 = GetStringParam(CmdStr, 1);
		str2 = GetStringParam(CmdStr, 2);
		Message.PutMessage( MSG_LOADPLAYER, GetIntParam(CmdStr,0),0,0, str1, str2);
		break;

	case 120:		//SwitchPlayer	两个int参数,表示主角编号,交换主角
		Message.PutMessage( MSG_SWITCHPLAYER, GetIntParam(CmdStr,0), GetIntParam(CmdStr, 1));
		break;

	case 121:		//SetPlayerNum	一个int参数,表示个数,设置主角个数
		Message.PutMessage( MSG_SETPLAYERNUM, GetIntParam(CmdStr,0));
		break;

	case 122:		//MoveDirectTo 两个int参数,一个是方向一个是步数
		Message.PutMessage(MSG_MOVEDIRECTTO,GetIntParam(CmdStr,0),GetIntParam(CmdStr,1));
		break;

	case 200:		//Talk			一个string参数,显示开场白对话,对话内容中<CR>代表换行
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_TALK, 0, 0, 0, str1 );
		break;

	case 201:		//Say		三个参数,两个string参数接一个int(不是必须)参数,缺省是1(左)
		{			//				前两个是对话,和人物头像,后一个是显示头像在左边还是右边
			str1 = GetStringParam(CmdStr, 0);
			char *temp=GetStringParam(CmdStr, 1);
			int photo = GetIntParam(CmdStr,2);
			if( photo == ERROR_DATA )
			{
				photo = 1;
			}
			Message.PutMessage( MSG_SAY, photo, 0, 0, str1,temp);
		}
		break;

	case 210:		//AddMoney		一个int参数表示增加的金钱数目
		Message.PutMessage( MSG_ADDMONEY, GetIntParam(CmdStr, 0));
		break;

	case 221:		//AddObject		一个string接一个int,添加string物品int个
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_ADDOBJECT, GetIntParam(CmdStr, 1), 0, 0, str1);
		break;

	case 222:		//DelObject		一个string接一个int,删除string物品int个
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_DELOBJECT, GetIntParam(CmdStr, 1), 0, 0, str1);
		break;

	case 223:		//CheckObject	一个string参数,一个全局变量,检查string物品
		{			//								有多少,结果放到全局变量中
					//								在这个语句后请用break;
			char *strGoods = GetStringParam(CmdStr, 0);
			char *var=GetVariableParam(CmdStr, 1);
			int num = role[0].CheckObject(strGoods);
			SetValue(var, num);
		}
		break;

	case 224:		//AddMagic 一个string参数接一个int参数
		{			//			一个是魔法名,一个是学会这个魔法的主角
			str1 = GetStringParam(CmdStr,0);
			int rolenum = GetIntParam(CmdStr,1);
			Message.PutMessage(MSG_ADDMAGIC,rolenum,0,0,str1);
			break;
		}

	case 225:		//DelMagic 一个string参数接一个int参数
		{			//			一个是魔法名,一个是拥有这个魔法的主角
			str1 = GetStringParam(CmdStr,0);
			int rolenum = GetIntParam(CmdStr,1);
			Message.PutMessage(MSG_DELMAGIC,rolenum,0,0,str1);
			break;
		}

	case 250:		//MoveNpcTo		三个参数,一个string接两个int,移动名字叫string的
					//				NPC到两个int构成的坐标,这个时候是不会执行下一条消息的
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_MOVENPCTO, GetIntParam(CmdStr,1), GetIntParam(CmdStr,2),
							0, str1);
		break;

	case 251:		//MoveNPC		和上一个基本相同,但是会继续执行消息
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_MOVENPC, GetIntParam(CmdStr,1), GetIntParam(CmdStr,2), 0, 
							str1);
		break;

	case 252:		//SetNpcPos		四个参数,一个string三个int,设置名叫string到后两个int
					//						  组成的坐标,最后一个不是必须的,有,表示清除原
					//						  位置的阻挡关系
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SETNPCPOS, GetIntParam(CmdStr,1), GetIntParam(CmdStr,2), 
					GetIntParam(CmdStr,3), str1 );
		break;

	case 253:		//SetNpcDir		一个string参数接一个int参数,和SetPlayDir相同
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SETNPCDIR, GetIntParam(CmdStr,1), 0,0, str1 );
		break;

	case 254:		//SetNpcStep	一个string参数接一个int参数,
					//				设置string的NPC的当前步是int的值
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SETNPCSTEP, GetIntParam(CmdStr,1), 0,0, str1 );
		break;

	case 255:		//AddNpc		两个string参数,接两个不必须的int参数
					//				NPC放在第一个string表示的ini文件的由第二个string表示的
					//				index索引中,后两个是坐标,没有的话就用ini文件里的坐标
		str1 = GetStringParam(CmdStr, 0);
		str2 = GetStringParam(CmdStr, 1);
		Message.PutMessage( MSG_ADDNPC, GetIntParam(CmdStr,2), GetIntParam(CmdStr,3),
					0, str1, str2);
		break;

	case 256:		//DelNpc		一个表示NPC名字的string参数
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_DELNPC, 0, 0, 0, str1);
		break;

	case 257:		//SetNpcActive	一个表示NPC名字的string参数接一个表示是否活动的int参数
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SETNPCACTIVE, GetIntParam(CmdStr,1), 0,0, str1);
		break;

	case 258:		//SetNpcShow	一个表示NPC名字的string参数接一个表示是否显示的int参数
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SETNPCSHOW, GetIntParam(CmdStr,1), 0,0, str1);
		break;

	case 259:		//SetNpcScript	一个表示NPC名字的string参数接一个表示脚本文件的string参数
		str1 = GetStringParam(CmdStr, 0);
		str2 = GetStringParam(CmdStr, 1);
		Message.PutMessage( MSG_SETNPCSCRIPT, 0,0,0, str1, str2);
		break;

	case 300:		//Delay			一个int参数,延时
		Message.PutMessage( MSG_DELAY, GetIntParam(CmdStr,0), 0, 0, NULL);
		break;

	case 301:		//FadeIn		三个int参数,效果颜色时间(后两个不是必须),屏幕淡入
		Message.PutMessage( MSG_FADEIN, GetIntParam(CmdStr,0), GetIntParam(CmdStr, 1), 
			GetIntParam(CmdStr,2), NULL);
		break;
	
	case 302:		//FadeOut		两个int参数,效果加时间(时间不是必须的),屏幕淡出
		Message.PutMessage( MSG_FADEOUT, GetIntParam(CmdStr,0), GetIntParam(CmdStr, 1), 0,
			NULL);
		break;

	case 303:		//PlayMusic		一个string参数,播放背景音乐(循环)
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_PLAYMUSIC, 0,0,0, str1 );
		break;

	case 304:		//StopMusic		没有参数,停止播放背景音乐
		Message.PutMessage( MSG_STOPMUSIC );
		break;

	case 305:		//PauseMusic	没有参数,继续播放背景音乐
		Message.PutMessage( MSG_PAUSEMUSIC );
		break;

	case 306:		//ResumeMusci	没有参数,暂停播放背景音乐
		Message.PutMessage( MSG_RESUMEMUSIC );
		break;

	case 310:		//PlaySound		一个string参数,播放一个音效(单次)
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_PLAYSOUND, 0,0,0, str1 );
		break;

	case 311:		//StopSound		没有参数,停止播放音效
		Message.PutMessage( MSG_STOPSOUND );
		break;

	case 340:		//GameMessage	四个参数,一个string接三个int,显示一条游戏消息
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_GAMEMESSAGE, GetIntParam(CmdStr,1), 
			GetIntParam(CmdStr,2), GetIntParam(CmdStr,3), str1);
		break;

	case 350:		//ShowMessage	四个参数,一个string接三个int,显示一条系统消息
		str1 = GetStringParam(CmdStr, 0);
		Message.PutMessage( MSG_SHOWMESSAGE, GetIntParam(CmdStr,1), GetIntParam(CmdStr,2), 
			GetIntParam(CmdStr,3), str1);
		break;
	}

	return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -