www.pudn.com > MUDGame.rar > Client.cpp
#include#include #include #include #include #include #include "tinyxml.h" #define _CLIENT_INCLUDE_ #include "..\Common Include\CommonInclude.h" #define PORT 5050 #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"tinyxmld") #pragma comment(lib,"winmm") using namespace std; //网络部分函数 SOCKET ConnectServer(char* szServerIP,int port); //游戏部分函数 void showLoginMenu(SOCKET); void showMainMenu(SOCKET); bool initGameCondition(SOCKET); void CreateRoleMenu(SOCKET sock); bool Auth(SOCKET sock,char*szName,char*szPass); bool RegisterUser(SOCKET sock,char* szName,char *szPass); void ShowMap(); bool GetOnlineRoleList(SOCKET); void ShowSystemInfo(); void ShowStatus(SOCKET); char* GetStringByOccuType(occupation occ); void ShowMapInfo(int mapx,int mapy); void UpdateData(SOCKET); bool NextMapScence(dir); void SaveGameData(SOCKET); void CreateGameEvent(SOCKET); void GetTreasureEvent(SOCKET); void MeetEnemyEvent(SOCKET); void DefaultEvent(SOCKET); void ColorTextOut(const char * str,bool bUnderLine); int GetEquipValueByString(SOCKET,string&); bool GetObjectInfo(SOCKET,string&,Myobject&); void UseThinginPackage(SOCKET sock); void ShowDialogMenu(SOCKET); void GetGameMessage(SOCKET); char* GetStringByObjType(objectType ot); void SetHMTop(SOCKET); void SellObject(SOCKET); bool GetMonsterInfo(SOCKET,monster&); void CalculateRoleInfo(SOCKET,int&,int&,int&); void GetSkillParamByString(SOCKET sock,string& str,skill&); void UpdateAfterFight(SOCKET); //全局变量 player g_player; vector g_OnLineRoles; const char* g_szfile="clientdata.xml"; int hpTop;//用来控制HP上限 int mpTop;//用来控制mp上限 bool reborth=false;//是否重生 void main(int argc,char* argv[]) { system("title 武林群侠传"); //SetConsoleTitle("武林群侠传"); //HANDLE hWnd; //hWnd=GetStdHandle(STD_OUTPUT_HANDLE); //SetConsoleTextAttribute(hWnd,FOREGROUND_GREEN|FOREGROUND_BLUE|COMMON_LVB_UNDERSCORE); WSADATA wsd; if(WSAStartup(0x0202,&wsd)!=0) { cout<<"wsastartup() failed"< >szServerIP; client=ConnectServer(szServerIP,PORT); if(client==NULL) { cout<<"连接服务器失败!"< 探索地图"< 对外发话"< 查看状态"< 显示地图"< 向东行进"< 向南行进"< 向西行进"< 向北行进"< 使用物品"< 退出游戏"< >in; if(in>'9'||in<'0') { cout<<"输入非法,请输入0-9"< 登陆"< 注册"< 退出"< >choice; switch(choice) { case 1: cout<<"************************************************************"< >szName; cout<<"请输入你的密码:"; cin>>szPass; if(Auth(sock,szName,szPass)) { isgoon=false; } else system("pause"); break; case 2: char szrePass[20]; memset(szrePass,0,20); cout<<"************************************************************"< >szName; cout<<"请输入你想注册的密码:"; cin>>szPass; cout<<"请再次输入你的密码:"; cin>>szrePass; if(strcmp(szPass,szrePass)==0) { if(RegisterUser(sock,szName,szPass)) { CreateRoleMenu(sock); //cout<<"请用你注册的帐户登陆吧!"< 战士"< 法师"< 道士"< >choice; switch(choice) { case 1: tplayer.ownOccup=OC_WARRIOR; iswelldone=true; break; case 2: tplayer.ownOccup=OC_RABBI; iswelldone=true; break; case 3: tplayer.ownOccup=OC_DOCTOR; iswelldone=true; break; default: cout<<"输入非法,请输入1-3数字!"< 男"< 女"< >choice; switch(choice) { case 1: tplayer.ownSex=MALE; iswelldone=true; break; case 2: tplayer.ownSex=FEMALE; iswelldone=true; break; default: cout<<"输入非法,请输入1-2数字!"< >szName; if(strlen(szName)>=20) { cout<<"你的输入的字符太多!"< =5&&random<50) { //遇敌事件 MeetEnemyEvent(sock); } if(random>=50) { //一般描述事件 DefaultEvent(sock); } } //获得宝物事件,概率为5% void GetTreasureEvent(SOCKET sock) { srand(timeGetTime()); int item=rand()%5; bool welldone=false; ColorTextOut("[系统]由于你的人品爆发,你获得了传说中的宝物!",false); cout< 等级增加->属性值增加(基本属性及新技能),金钱增加,没有装备掉落 // void MeetEnemyEvent(SOCKET sock) { monster mon; int totalAK=0,totalDF=0,totalCT=0;//综合伤害值,防御值,敏捷值 CalculateRoleInfo(sock,totalAK,totalDF,totalCT); if(!GetMonsterInfo(sock,mon)) { cout<<"从服务器端读取怪物数据失败"< sklib;//技能库信息 vector mdlib;//药品库信息 //统计拥有技能,以获取技能参数 for(int i=0;i =mon.ct)//玩家先出手 { PL:cout<<"*************技能攻击**************"< >in; if(in>'9'||in<'0') { //cout<<"输入非法,请输入0-9"< 0) { cout<<"你使出了一招——"; ColorTextOut(g_player.ownSkill[choice].c_str(),false); cout< 0)//怪物防御太高了 temphp=sklib[choice].damage-mon.defence; else temphp=1;//至少一点血 cout< 0) { g_player.hp+=mdlib[whatuse].value; g_player.ownObject[hpindex].num--; } } else { if(g_player.ownObject[mpindex].num-1>0) { g_player.mp+=mdlib[whatuse].value; g_player.ownObject[mpindex].num--; } } goto GW; } else//使用物理攻击 { WL:if((g_player.attack-mon.defence)>0) temphp=g_player.attack-mon.defence; else temphp=1; mon.hp-=temphp; if(mon.hp<=0)//战斗胜利 { g_player.exp+=mon.hasexp; g_player.money+=mon.hasmoney; //奖励提示: ColorTextOut("[系统]你获得了",false); cout< 0)//mp够发动技能 { ColorTextOut("惊叹!!!",false); cout< 0)//玩家防御太高了 temphp=mon.skilldamage-g_player.defendence; else temphp=1;//最少1点血 mon.mp-=mon.needmp; g_player.hp-=temphp; cout<<"你一声闷哼,中招了,耗去了"< 0) temphp=mon.attack-g_player.defendence; else temphp=1; g_player.hp-=temphp; cout<<"你被耗去了"< =10) if((g_player.money-50*g_player.level)>0) g_player.money-=50*g_player.level; else g_player.money=0; system("pause");//暂停 reborth=true; showMainMenu(sock); //退出战斗 return; } else goto PL; } } } ColorTextOut("[系统]退出战斗模式",false); UpdateAfterFight(sock); } void UpdateAfterFight(SOCKET sock) { //先判断是否达到升级条件 SCommand scom; scom.CommandID=CMD_GETLEVELINFO; char lv[3]; itoa((g_player.level+1),lv,10);//取得下一级的数据 scom.DataSize=(int)strlen(lv); int nRet=send(sock,(char*)&scom,sizeof(scom),0); if(nRet==SOCKET_ERROR) { cout<<"UpdateAfterFight()发送数据出错,请检查网络!"< li.needexp)//升级后数据的更改 { g_player.level++; g_player.hp=li.hp; g_player.mp=li.mp; g_player.attack=li.attack; g_player.defendence=li.defendence; g_player.celerity=li.celerity; g_player.exp-=li.needexp; if(strcmp(li.hasskill,"null")!=0)//等级提高,学习新技能 { int i=0; for(;i SuperMarket; char* curScence=map[g_player.pos[0]][g_player.pos[1]]; SCommand scom; scom.CommandID=CMD_CHECKHASNPC; scom.DataSize=(int)strlen(curScence); int nRet=send(sock,(char*)&scom,sizeof(scom),0); if(nRet==SOCKET_ERROR) { cout<<"DefaultEvent()发送数据出错,请检查网络!"< 够买"< 抛售"< 离开"< >in; if(in<'0'||in>'4') return; else choice=in-'0'; switch(choice) { case 1: cout<<"请选择你要够买物品的序号:(序号外任意键退出)"< >itemchoice; if(itemchoice>=objnum||itemchoice<0) break; cout<<"请输入你要够买的数量:"< >itemnum; if(SuperMarket[itemchoice].buy*itemnum>g_player.money) cout<<"你的钱不够!"< >choice; if(choice>=index||choice<0) { cout<<"输入非法,请输入数字0-"< >itemnum; Myobject mobj; memset(&mobj,0,sizeof(mobj)); bool bfirstsucess=false; bool bsecondsucess=false; SCommand scom; memset(&scom,0,sizeof(scom)); updateNewDS useupdata; memset(&useupdata,0,sizeof(useupdata)); updateNewDS effupdata; memset(&effupdata,0,sizeof(effupdata)); if(GetObjectInfo(sock,g_player.ownObject[choice].ownObjectName,mobj)) { if(g_player.ownObject[choice].num 0) { g_player.ownObject[choice].num-=itemnum; useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectnum%d",choice+1);//数据库从1开始 useupdata.opType=DBOP_TYPE_NUM; strcpy(useupdata.item,"null"); } else if(g_player.ownObject[choice].num-itemnum==0)//该物品全卖 { g_player.ownObject[choice].num-=itemnum; g_player.ownObject[choice].ownObjectName="null"; useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectname%d objectnum%d",choice+1,choice+1);//数据库从1开始 useupdata.opType=DBOP_TYPE_ALL; strcpy(useupdata.item,"null"); } //公共部分 g_player.money+=(mobj.buy*itemnum)/2; effupdata.num=g_player.money; strcpy(effupdata.op,"tael"); effupdata.opType=DBOP_TYPE_NUM; strcpy(effupdata.item,"null"); scom.CommandID=CMD_UPDATE; scom.DataSize=sizeof(useupdata); int nRet=send(sock,(char*)&scom,sizeof(scom),0); if(nRet==SOCKET_ERROR) { cout<<"SellObject()发送数据出错,请检查网络!"< ::iterator iter=g_OnLineRoles.begin();iter!=g_OnLineRoles.end();iter++) { cout<<"["<nName<<" "; if(i%4==0) cout< >choice; if(choice>(int)(g_OnLineRoles.size()-1)||choice<0) return; cout<<"请输入你要说的内容:"< >diag; //消息封装 strcat(rebuilt,g_player.nickName); strcat(rebuilt," "); strcat(rebuilt,diag); strcpy(mess.message,rebuilt); strcpy(mess.recver,g_OnLineRoles[choice].uName); SCommand scom; scom.CommandID=CMD_SPEAK; scom.DataSize=sizeof(mess); int nRet=send(sock,(char*)&scom,sizeof(scom),0); if(nRet==SOCKET_ERROR) { cout<<"发送说话数据出错,请检查网络!"< =0) { g_player.pos[1]-=1; } else bGone=false; break; case NORTH: if(g_player.pos[0]-1>=0) { g_player.pos[0]-=1; } else bGone=false; break; } return bGone; } //根据mapx,mapy值显示地图信息 void ShowMapInfo(int mapx,int mapy) { TiXmlDocument doc(g_szfile); if(!doc.LoadFile()) { cout<<"导入地图数据时,出现错误!请核实你的客户端资源!"< FirstChild()->FirstChild(); for(;node;node=node->NextSibling()) { if(node->FirstChild()->Type()==TiXmlNode::ELEMENT) { if(strcmp(node->FirstChild()->ToElement()->GetText(),curMapName)==0) { ColorTextOut("[系统]",false); cout< FirstChild()->NextSibling()->ToElement()->GetText()< ::iterator iter=g_OnLineRoles.begin();iter!=g_OnLineRoles.end();iter++) { cout<<"["<nName<<" "; if(i%4==0) cout< >in; if(in>'9'||in<'0') { break; } choice=in-'0';//还原成数字 if(g_player.ownObject[choice].ownObjectName=="null") { cout<<"改格子没有存放任何物品!"< hpTop)//大于hp上限 g_player.hp=hpTop; effupdata.num=g_player.hp; strcpy(effupdata.op,"hp"); strcpy(effupdata.item,"null"); effupdata.opType=DBOP_TYPE_NUM; break; case OT_MP: g_player.ownObject[choice].num-=1; //当某物品用完了 if(g_player.ownObject[choice].num==0) { //使用数据 strcpy(useupdata.item,"null"); useupdata.opType=DBOP_TYPE_ALL; useupdata.num=0; sprintf(useupdata.op,"objectname%d,objcetnum%d",choice+1,choice+1); //更新本地状态 g_player.ownObject[choice].ownObjectName="null"; g_player.ownObject[choice].num=0; } else//还有某物品剩余 { useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectnum%d",choice+1); strcpy(useupdata.item,"null"); useupdata.opType=DBOP_TYPE_NUM; } //效果数据,公共部分 g_player.mp+=mobj.value; if(g_player.hp>mpTop)//大于hp上限 g_player.mp=mpTop; effupdata.num=g_player.mp; strcpy(effupdata.op,"mp"); strcpy(effupdata.item,"null"); effupdata.opType=DBOP_TYPE_NUM; break; //装备的更新 //从背包里减去该装备,在装备栏增加该装备,原已有装备,交换之。当换上的装备有多余时,需一格空间存储换下来的装备,如无,则换装失败 // //装备类物品使用 case OT_ARMOUR: if(g_player.ownEquip[0]=="null")//原来装备为空 { if(g_player.ownObject[choice].num>1)//背包里有多件本装备 { //本地数据修改 g_player.ownObject[choice].num-=1; //数据报封装 useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectnum%d",choice+1); strcpy(useupdata.item,"null"); useupdata.opType=DBOP_TYPE_NUM; //身上装备数据修改 g_player.ownEquip[0]=g_player.ownObject[choice].ownObjectName; //身上装备数据包封装 sprintf(effupdata.op,"equipname%d",1); strcpy(effupdata.item,g_player.ownEquip[0].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; } else//仅此一件 { //身上装备数据修改 g_player.ownEquip[0]=g_player.ownObject[choice].ownObjectName; //身上装备数据包封装 sprintf(effupdata.op,"equipname%d",1); strcpy(effupdata.item,g_player.ownEquip[0].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; //换下装备数据修改 g_player.ownObject[choice].ownObjectName="null"; g_player.ownObject[choice].num-=1; //数据包封装 useupdata.num=g_player.ownObject[choice].num; strcpy(useupdata.item,g_player.ownObject[choice].ownObjectName.c_str()); sprintf(useupdata.op,"objectname%d objectnum&d",choice+1,choice+1); useupdata.opType=DBOP_TYPE_ALL; } } else//原来已有装备,换装 { //转换中间量 string temp; temp=g_player.ownEquip[0]; bool bGeted=false;//找到标识 bool bInsert=false; if(g_player.ownObject[choice].num>1)//背包里有多于1件的该装备 { for(int i=0;i 1)//背包里有多件本装备 { //换上装备数据修改 g_player.ownObject[choice].num-=1; //换上装备数据报封装 useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectnum%d",choice+1); strcpy(useupdata.item,"null"); useupdata.opType=DBOP_TYPE_NUM; //身上装备数据修改 g_player.ownEquip[1]=g_player.ownObject[choice].ownObjectName; //身上装备数据修改 sprintf(effupdata.op,"equipname%d",2); strcpy(effupdata.item,g_player.ownEquip[1].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; } else//仅此一件 { //身上装备数据修改 g_player.ownEquip[1]=g_player.ownObject[choice].ownObjectName; //身上装备数据修改 sprintf(effupdata.op,"equipname%d",2); strcpy(effupdata.item,g_player.ownEquip[1].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; //换上装备数据修改 g_player.ownObject[choice].ownObjectName="null"; g_player.ownObject[choice].num-=1; //换上装备数据包封装 useupdata.num=g_player.ownObject[choice].num; strcpy(useupdata.item,g_player.ownObject[choice].ownObjectName.c_str()); sprintf(useupdata.op,"objectname%d objectnum&d",choice+1,choice+1); useupdata.opType=DBOP_TYPE_ALL; } } else//原来已有装备,换装 { //转换中间量 string temp; temp=g_player.ownEquip[1]; bool bGeted=false;//找到标识 bool bInsert=false; if(g_player.ownObject[choice].num>1)//背包里有多于1件的该装备 { for(int i=0;i 1)//背包里有多件本装备 { //本地数据修改 g_player.ownObject[choice].num-=1; //数据报封装 useupdata.num=g_player.ownObject[choice].num; sprintf(useupdata.op,"objectnum%d",choice+1); strcpy(useupdata.item,"null"); useupdata.opType=DBOP_TYPE_NUM; //身上装备数据修改 g_player.ownEquip[2]=g_player.ownObject[choice].ownObjectName; //身上装备数据包封装 sprintf(effupdata.op,"equipname%d",3); strcpy(effupdata.item,g_player.ownEquip[2].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; } else//仅此一件 { //身上装备数据修改 g_player.ownEquip[2]=g_player.ownObject[choice].ownObjectName; //身上装备数据包封装 sprintf(effupdata.op,"equipname%d",3); strcpy(effupdata.item,g_player.ownEquip[2].c_str()); effupdata.opType=DBOP_TYPE_STRING; effupdata.num=0; //换下装备数据修改 g_player.ownObject[choice].ownObjectName="null"; g_player.ownObject[choice].num-=1; //数据包封装 useupdata.num=g_player.ownObject[choice].num; strcpy(useupdata.item,g_player.ownObject[choice].ownObjectName.c_str()); sprintf(useupdata.op,"objectname%d objectnum%d",choice+1,choice+1); useupdata.opType=DBOP_TYPE_ALL; } } else//原来已有装备,换装 { //转换中间量 string temp; temp=g_player.ownEquip[2]; bool bGeted=false;//找到标识 bool bInsert=false; if(g_player.ownObject[choice].num>1)//背包里有多于1件的该装备 { for(int i=0;i