📄 cbctrls.cpp
字号:
/////////////////
// CBCtrlS.cpp : << chibi >> global contral data structure
// v0014 : Feb.16.1997,devided from CBCTRL.cpp
// v0020 : Mar.29.1997,add most controls
// written by : Liu Gang
// Compiler : Visual C++ 4.2
// Copyright : WayAhead Co.Ltd. 1996-1997
/////////////////
// 此文件包含游戏对控制结构(命令,状态,步,帧)的处理
#include "stdafx.h"
#include "Assert.h"
#include "CBCTRL.h"
#include "CBShadow.h"
#include "CBMini.h"
#include "CBDATA.h"
#include "CBEyes.h"
//////////////////////
// Dong hai, 行军算法
#include "March_n.h"
extern BYTE MARCH_TrackForward[NUMBER_OF_TRACK];//此数组为用来存储最后由行军轨迹求出的行军路线的方向变化
extern short MARCH_Track[NUMBER_OF_TRACK][3];//此数组为用来存储最后的行军轨迹的数组
//////////////////////
// LHJ
#include "marco.h" // BUTTON_UP BUTTON_DISABLE
#include "interfac.h" // FACE_SetNumberButtonState(int number, int state);
#include "cbprompt.h" // FACE_UpdateExperience(), FACE_UpdateSoldierNumber()
// LHJ
//////////////////////
//////////////////////
// externals
extern int MAP_nLocationNum[4]; // defined in CBMap.cpp
extern POINT MAP_ptLocation[2][MAP_LOCATION_MAX]; // defined in CBMap.cpp
extern int MAP_nDrawNum[4]; // defined in CBMap.cpp
//////////////////////
//////////////////////
// local functions
// 在刚刚创建单元后,使用此函数对该单元赋给属性值
void CTRL_SetUnitAttribute( struct UNIT_STRUCT *pUnit );
//////////////////////
//////////////////////
// 状态处理
// Status
//////////////////////
// check each unit if should change Status
void CTRL_STATUS_Main()
{
for( int i=0; i<GAME_PLAYER_MAX; i++ )
{
#ifdef _DEBUG
int nCounter=0;
#endif
for( int j=0; j<PLAYER_UNIT_MAX; j++ )
{
if( GAME.Players[i].Unit[j].nType != MAP_UNIT_TYPE_NONE )
{
CTRL_STATUS_Change( &GAME.Players[i].Unit[j] );
#ifdef _DEBUG
nCounter++;
#endif
}
}
#ifdef _DEBUG
if( GAME.Players[i].wUnitCounter!= nCounter )
OutputDebugString( "CTRL_STATUS_Main Error(0): Unit number check error!\n" );
#endif
}
}
// change the Status of the unit
// pUnit : the unit to be changed to
inline void CTRL_STATUS_Change( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit->nType != MAP_UNIT_TYPE_NONE );
// 死亡时不响应任何命令
if( EYE_IfUnitIsDead( pUnit ) ) return; // has dead
#ifdef _DEBUG
// 是否要从建筑里出来
if( pUnit->nHasShadow == 0 )
{
Assert( pUnit->Status.bIRQ == TRUE );
pUnit->Status.bIRQ = TRUE;
}
#endif
if( pUnit->Task.nTaskID == QUXIAO ) return; // no command at all
////////////////////////////
// 清除Bug!!!
// 必须当单元完成一个“步”操作后,才能接收新的命令
if( pUnit->Draw.ptOff.x != 0 || pUnit->Draw.ptOff.y != 0 )
return;
////////////////////////////
// new command
// 新命令,TASK的nTaskID不为QUXIAO,bDone为TRUE
if( pUnit->Task.bDone )
{
Assert( pUnit->Draw.ptOff.x == 0 || pUnit->Draw.ptOff.y == 0 );
#ifdef _DEBUG_OFFSET_
if( pUnit->Draw.ptOff.x != 0 || pUnit->Draw.ptOff.y != 0 )
{
// WriteLogFile( "off.log", "change0\n" );
}
#endif //_DEBUG_OFFSET_
// 对某些旧命令要有一些结束的操作
if( pUnit->Status.nTaskID == GONGJI )
{
Assert( pUnit->Status.nTaskIDEx == 2 );
Assert( pUnit->Status.nParam1 != MAP_DATA_NONE );
struct UNIT_STRUCT *pU = MAP_GetUnit( pUnit->Status.nParam1 );
Assert( pU );
pU->nIDAttackMe = MAP_DATA_NONE;
}
pUnit->nIDAttackMe = MAP_DATA_NONE;
if( pUnit->Status.nTaskID == YUNSONG
&& pUnit->Status.nTaskIDEx == 1
&& EYE_IfUnitIsWorker( pUnit )
&& pUnit->Status.bDone == FALSE )
{
int nDir;
nDir = pUnit->Draw.nDir;
int bOdd = pUnit->Draw.nY&1;
int nX = pUnit->Draw.nX + MAP_ptSenser[bOdd][0][nDir].x;
int nY = pUnit->Draw.nY + MAP_ptSenser[bOdd][0][nDir].y;
WORD codeG = MAP_GetGroundData( pUnit->Draw.nLayer, nX, nY );
if( codeG != MAP_DATA_NONE )
{
struct MAP_GROUND_CODE_STRUCT stctG;
MAP_GroundDeCode( codeG, &stctG );
Assert( stctG.nAttr != MAP_SPECIAL_NONE );
Assert( stctG.nAttr == pUnit->Soldier.nResType+4 ); // 碰巧
stctG.nAttr -= 4; // 设置为采集完
codeG = MAP_GroundEnCode( stctG );
MAP_SetGroundData( pUnit->Draw.nLayer, nX, nY, codeG );
}
}
if( pUnit->Status.nTaskID == MFU )
{
CTRL_SetSTG( &pUnit->Draw, MAIFU, FALSE );
}
// 对于已经打开的门,则不再执行此命令
// Aug.8, 1997, Liu Gang
if( pUnit->Status.nTaskID == KAIMEN
&& pUnit->nCounter != 0 )
{
pUnit->Task.bDone = FALSE;
// 计数器不能为0
//pUnit->nCounter = 0;
return;
}
// OutputDebugString( "CTRL_TASK : New Command: " );
// OutputString( pUnit->Task.nID, "," );
// OutputString( pUnit->Task.nTaskID, "," );
// OutputString( pUnit->Task.nTaskIDEx, "\n" );
// set TASK to "doing"
// 设置完毕状态后,bDone为FALSE
pUnit->Task.bDone = FALSE;
pUnit->nCounter = 0;
// 运送任务,但是此时该单元已经携带有资源了
if( pUnit->Task.nTaskID == YUNSONG
&& EYE_IfUnitIsWorker( pUnit )
&& pUnit->Soldier.nResource > 0 )
{
// 设置该士兵为回送的任务
struct CTRL_TASK_STRUCT Task;
CTRL_TASK_Clear( &Task );
Task.nID = pUnit->nID;
// 目的地是所带资源的家
Task.nParam1 = TY_FindNearHome(pUnit->Draw.nPlayer,pUnit->Draw.nX, pUnit->Draw.nY, pUnit->Soldier.nResType);
if( Task.nParam1 == MAP_DATA_NONE )
{ // 如果没有老家,则结束命令
Task.nTaskID = JIESHU;
}
else
{
Task.nTaskID = HUISONG;
Task.nTaskIDEx = 2; // MOUSE_HITRESULT_UNIT
Task.nTaskIDEx2 = pUnit->Task.nTaskIDEx2; // 保存资源类型
if( pUnit->Task.nTaskIDEx == 1 ) // MOUSE_HITRESULT_GROUND
{
Task.nParam2 = pUnit->Task.nParam1; // 原来资源的位置Z
Task.nParam3 = pUnit->Task.nParam2; // 原来资源的位置X
Task.nParam4 = pUnit->Task.nParam3; // 原来资源的位置Y
}
else
{
Task.nParam4 = pUnit->Task.nParam1; // 保存原来的资源建筑ID
}
Assert( Task.nParam1 != MAP_DATA_NONE );
}
Task.bDone = TRUE;
CTRL_TASK_DeployByComputer( pUnit->Draw.nPlayer, &Task );
return;
}
if( (pUnit->Task.nTaskID == XIULI
|| (pUnit->Task.nTaskID == YIDONG && pUnit->Task.nTaskIDEx == 2) )
&& EYE_IfUnitIsWorker( pUnit )
&& pUnit->Soldier.nResType != QXZIYUAN
&& pUnit->Soldier.nResource > 0 )
{ // 把工人任务变为回送
struct UNIT_STRUCT *pU = MAP_GetUnit( pUnit->Task.nParam1 );
Assert( pU );
if( !EYE_IfUnitIsDead( pU )
&& EYE_IfUnitIsBuild( pU ) && (pU->Draw.nPlayer == pUnit->Draw.nPlayer) )
{
int nRes = EYE_GetUResHome( pU );
if( nRes == pUnit->Soldier.nResType || nRes == SUOYOUZY
|| (nRes == MAITIAN && pUnit->Soldier.nResType == LIANGCANG) )
{
struct CTRL_TASK_STRUCT Task;
CTRL_TASK_Clear( &Task );
Task.nID = pUnit->nID;
Task.nTaskID = HUISONG;
Task.nTaskIDEx = 2;
Task.nTaskIDEx2 = pUnit->Soldier.nResType; // 保存资源类型
if( pUnit->Soldier.nResType == 0
|| pUnit->Soldier.nResType == 1 )
{ // 地形类型资源
Task.nParam2 = pUnit->Draw.nLayer;
Task.nParam3 = pUnit->Draw.nX;
Task.nParam4 = pUnit->Draw.nY;
}
else
{ // 建筑类型资源
Task.nParam4 = MAP_DATA_NONE;
}
Task.nParam1 = pUnit->Task.nParam1; // 目的单元ID
Assert( Task.nParam1 != MAP_DATA_NONE );
Task.bDone = TRUE;
// 发送
CTRL_TASK_DeployByComputer( pUnit->Draw.nPlayer, &Task );
return;
}
}
}
// set status to unit
CTRL_TASK_Copy( &pUnit->Status, &pUnit->Task );
// change status if needed
// 对于多状态任务,设置其第一状态为移动
// if( pUnit->Status.nTaskID == JIANZAO ) // 建造
// pUnit->Status.nTaskIDEx = 1; //MOUSE_HITRESULT_GROUND,设置目的地类型
if( pUnit->Status.nTaskID == XIULI ) // 修理
Assert( pUnit->Status.nTaskIDEx == 2 );
// pUnit->Status.nTaskIDEx = 2; //MOUSE_HITRESULT_GROUND,设置目的地类型
// 卸载,当nTaskIDEx2为0时,要先移动后卸载
if( pUnit->Status.nTaskID == XIEZAI
&& pUnit->Status.nTaskIDEx2 == 0 )
{
pUnit->Status.nTaskID = YIDONG;
}
if( pUnit->Status.nTaskID == YUNZAI
&& !(EYE_IfUnitIsTransport( pUnit )
&& pUnit->Status.nTaskIDEx2 == 1) )
{
pUnit->Status.nTaskID = YIDONG;
}
if( !EYE_IfUnitIsBuild( pUnit ) )
{
switch( pUnit->Status.nTaskID )
{
case JIANZAO: // 建造
case GONGJI: // 攻击
case YUNSONG: // 运送
case XIULI: // 修理
//case ZHENXING: // 阵型
//case DANTIAO: // 单挑
case HUISONG: // 回送
pUnit->Status.nTaskID = YIDONG;
break;
}
}
// 设置动画帧状态
if( pUnit->Status.nTaskID == YIDONG
&& EYE_IfUnitIsWorker( pUnit )
&& pUnit->Soldier.nResource > 0 )
{
if( pUnit->Soldier.nResType == SHULIN ) // 树林
{
pUnit->Draw.nState = pUnit->Draw.nDir+
MAP_Lib.AniSeq[pUnit->Draw.nFile].nEventBegin[3];
}
else if( pUnit->Soldier.nResType == MAITIAN // 麦田
|| pUnit->Soldier.nResType == LIANGCANG ) // 粮仓
{
pUnit->Draw.nState = pUnit->Draw.nDir+
MAP_Lib.AniSeq[pUnit->Draw.nFile].nEventBegin[5];
}
else if( pUnit->Soldier.nResType == TIEKUANG ) // 铁矿
{
pUnit->Draw.nState = pUnit->Draw.nDir+
MAP_Lib.AniSeq[pUnit->Draw.nFile].nEventBegin[4];
}
else // 一般状态
{
pUnit->Draw.nState = pUnit->Draw.nDir;
}
}
else pUnit->Draw.nState = pUnit->Draw.nDir;
if( !EYE_IfUnitIsBuild( pUnit ) )
{
pUnit->Draw.nFrame = 1;
pUnit->Draw.nCol = MAP_Lib.AniSeq[pUnit->Draw.nFile].nAniSeq[pUnit->Draw.nState][pUnit->Draw.nFrame]+
MAP_Lib.AniSeq[pUnit->Draw.nFile].nOffset;
pUnit->Draw.nRow = 0;
}
// 对于移动状态,行军算法
if( pUnit->Status.nTaskID == YIDONG )
{
int nEndx, nEndy, nEndZ;
WORD codeG;
Assert( pUnit->Status.nParam2 <= MAP_Lib.szNum.cx ); // 层号
Assert( pUnit->Status.nParam3 <= MAP_Lib.szNum.cy ); // 层号
// 如果目的地和出发点一样,则状态结束,不结构化
if( pUnit->Draw.nX == pUnit->Status.nParam2 && pUnit->Draw.nY == pUnit->Status.nParam3 )
{
pUnit->Status.bDone = TRUE;
return;
}
BOOL bShouldDuSe = TRUE; // 当目的地到达不了时是否设置堵塞标志
if( pUnit->Status.nTaskIDEx == 1 ) // hit ground
{
POINT ptNew = MAP_FindRegion( pUnit->Status.nParam1, pUnit->Status.nParam2,pUnit->Status.nParam3, MAP_Lib.Unit[pUnit->Draw.nFile].nItems[0], pUnit->nID );
//Assert( ptNew.x!=-1 && ptNew.y!=-1 );
if( ptNew.x == -1 || ptNew.y == -1 )
{
ptNew.x = pUnit->Status.nParam2,
ptNew.y = pUnit->Status.nParam3;
bShouldDuSe = FALSE;// 如果没在附近找到可以到达的目的地,则不设置预堵塞
}
nEndZ = pUnit->Status.nParam1;
nEndx = ptNew.x,
nEndy = ptNew.y;
// 修改层号
for(;;)
{
codeG = MAP_GetGroundData( nEndZ, nEndx, nEndy );
if( codeG != MAP_DATA_NONE )
break;
if( nEndZ == 0 && codeG == MAP_DATA_NONE )
{
Assert(0);
break;
}
nEndZ--;
}
}
else if( pUnit->Status.nTaskIDEx == 2 ) //hit unit
{
Assert( pUnit->Status.nParam1 != MAP_DATA_NONE );
struct UNIT_STRUCT *pUnitE = MAP_GetUnit( pUnit->Status.nParam1 );
POINT ptNew = MAP_FindRegion( pUnitE->Draw.nLayer, pUnitE->Draw.nX, pUnitE->Draw.nY, MAP_Lib.Unit[pUnit->Draw.nFile].nItems[0], pUnit->nID );
//Assert( ptNew.x!=-1 && ptNew.y!=-1 );
if( ptNew.x == -1 )
{
ptNew.x = pUnit->Status.nParam2,
ptNew.y = pUnit->Status.nParam3;
bShouldDuSe = FALSE;// 如果没在附近找到可以到达的目的地,则不设置预堵塞
}
nEndZ = pUnitE->Draw.nLayer;
nEndx = ptNew.x,
nEndy = ptNew.y;
// 修改层号
for(;;)
{
codeG = MAP_GetGroundData( nEndZ, nEndx, nEndy );
if( codeG != MAP_DATA_NONE )
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -