512 lines
13 KiB
C
512 lines
13 KiB
C
#include "version.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
#include "buf.h"
|
|
#include "configfile.h"
|
|
#include "magic_base.h"
|
|
#include "magic.h"
|
|
|
|
static Magic *MAGIC_magic;
|
|
static int MAGIC_magicnum;
|
|
|
|
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
|
|
AttMagic *ATTMAGIC_magic;
|
|
int ATTMAGIC_magicnum;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct tagMagic_MagicFunctionTable
|
|
{
|
|
char *functionname; /* 呪術設定ファイルに書く関数の名前 */
|
|
MAGIC_CALLFUNC func; /* 実際に呼び出される関数 */
|
|
int hash; /* hash */
|
|
}MAGIC_MagicFunctionTable;
|
|
|
|
/* 呪術を増やしたらここに登録する事 */
|
|
static MAGIC_MagicFunctionTable MAGIC_functbl[] = {
|
|
{ "MAGIC_Recovery", MAGIC_Recovery, 0},
|
|
{ "MAGIC_OtherRecovery", MAGIC_OtherRecovery, 0},
|
|
{ "MAGIC_FieldAttChange", MAGIC_FieldAttChange, 0},
|
|
{ "MAGIC_StatusChange", MAGIC_StatusChange, 0},
|
|
{ "MAGIC_MagicDef", MAGIC_MagicDef, 0},
|
|
{ "MAGIC_StatusRecovery", MAGIC_StatusRecovery, 0},
|
|
{ "MAGIC_Ressurect", MAGIC_Ressurect, 0},
|
|
{ "MAGIC_AttReverse", MAGIC_AttReverse, 0},
|
|
{ "MAGIC_ResAndDef", MAGIC_ResAndDef, 0},
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
{ "MAGIC_AttMagic" , MAGIC_AttMagic , 0 },
|
|
#endif
|
|
#ifdef _OTHER_MAGICSTAUTS
|
|
{ "MAGIC_MagicStatusChange", MAGIC_MagicStatusChange, 0},
|
|
#endif
|
|
#ifdef _ITEM_METAMO
|
|
{ "MAGIC_Metamo", MAGIC_Metamo, 0},
|
|
#endif
|
|
#ifdef _ITEM_ATTSKILLMAGIC
|
|
//{ "MAGIC_AttSkill", MAGIC_AttSkill, 0},
|
|
#endif
|
|
#ifdef _MAGIC_WEAKEN // vincent 精灵:虚弱
|
|
{ "MAGIC_Weaken", MAGIC_Weaken, 0},
|
|
#endif
|
|
#ifdef _MAGIC_DEEPPOISON // vincent 精灵:剧毒
|
|
{ "MAGIC_StatusChange2", MAGIC_StatusChange2,0},
|
|
#endif
|
|
#ifdef _MAGIC_BARRIER // vincent 精灵:魔障
|
|
{ "MAGIC_Barrier", MAGIC_Barrier, 0},
|
|
#endif
|
|
#ifdef _MAGIC_NOCAST // vincent 精灵:沉默
|
|
{ "MAGIC_Nocast", MAGIC_Nocast, 0},
|
|
#endif
|
|
#ifdef _MAGIC_TOCALL // 奔龙阵
|
|
{ "MAGIC_ToCallDragon", MAGIC_ToCallDragon, 0},
|
|
#endif
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
/* 基本チェック,アクセス関係 */
|
|
/*----------------------------------------------------------------------*/
|
|
INLINE BOOL MAGIC_CHECKINDEX( int index )
|
|
{
|
|
if( MAGIC_magicnum<=index || index<0 )return FALSE;
|
|
return TRUE;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static INLINE BOOL MAGIC_CHECKINTDATAINDEX( int index)
|
|
{
|
|
if( MAGIC_DATAINTNUM <= index || index < 0 ) return FALSE;
|
|
return TRUE;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static INLINE BOOL MAGIC_CHECKCHARDATAINDEX( int index)
|
|
{
|
|
if( MAGIC_DATACHARNUM <= index || index < 0 ) return FALSE;
|
|
return TRUE;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
INLINE int MAGIC_getInt( int index, MAGIC_DATAINT element)
|
|
{
|
|
return MAGIC_magic[index].data[element];
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
INLINE int MAGIC_setInt( int index, MAGIC_DATAINT element, int data)
|
|
{
|
|
int buf;
|
|
buf = MAGIC_magic[index].data[element];
|
|
MAGIC_magic[index].data[element]=data;
|
|
return buf;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
INLINE char* MAGIC_getChar( int index, MAGIC_DATACHAR element)
|
|
{
|
|
if( !MAGIC_CHECKINDEX( index)) return "\0";
|
|
if( !MAGIC_CHECKCHARDATAINDEX( element)) return "\0";
|
|
return MAGIC_magic[index].string[element].string;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
INLINE BOOL MAGIC_setChar( int index ,MAGIC_DATACHAR element, char* new )
|
|
{
|
|
if(!MAGIC_CHECKINDEX(index))return FALSE;
|
|
if(!MAGIC_CHECKCHARDATAINDEX(element))return FALSE;
|
|
strcpysafe( MAGIC_magic[index].string[element].string,
|
|
sizeof(MAGIC_magic[index].string[element].string),
|
|
new );
|
|
return TRUE;
|
|
}
|
|
/*----------------------------------------------------------------------
|
|
* 魔法の数を知る。
|
|
*---------------------------------------------------------------------*/
|
|
int MAGIC_getMagicNum( void)
|
|
{
|
|
return MAGIC_magicnum;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
* 魔法の設定ファイルを読む
|
|
*---------------------------------------------------------------------*/
|
|
BOOL MAGIC_initMagic( char *filename)
|
|
{
|
|
FILE* f;
|
|
char line[256];
|
|
int linenum=0;
|
|
int magic_readlen=0;
|
|
int i,j;
|
|
|
|
int max_magicid =0;
|
|
char token[256];
|
|
|
|
f = fopen(filename,"r");
|
|
if( f == NULL ){
|
|
print( "文件打开失败\n");
|
|
return FALSE;
|
|
}
|
|
|
|
MAGIC_magicnum=0;
|
|
|
|
/* まず有効な行が何行あるかどうか調べる */
|
|
while( fgets( line, sizeof( line ), f ) ){
|
|
linenum ++;
|
|
if( line[0] == '#' )continue; /* comment */
|
|
if( line[0] == '\n' )continue; /* none */
|
|
chomp( line );
|
|
|
|
#ifdef _MAGIC_OPTIMUM // Robin 取出最大MAGIC ID
|
|
if( getStringFromIndexWithDelim( line, ",", MAGIC_DATACHARNUM+MAGIC_ID+1,
|
|
token, sizeof(token)) == FALSE )
|
|
continue;
|
|
max_magicid = max( atoi( token), max_magicid);
|
|
#endif
|
|
|
|
MAGIC_magicnum++;
|
|
}
|
|
|
|
#ifdef _MAGIC_OPTIMUM
|
|
print("有效魔法:%d 最大魔法:%d ...", MAGIC_magicnum, max_magicid);
|
|
MAGIC_magicnum = max_magicid +1;
|
|
#endif
|
|
|
|
if( fseek( f, 0, SEEK_SET ) == -1 ){
|
|
fprint( "搜索错误\n" );
|
|
fclose(f);
|
|
return FALSE;
|
|
}
|
|
|
|
MAGIC_magic = allocateMemory( sizeof(struct tagMagic)
|
|
* MAGIC_magicnum );
|
|
if( MAGIC_magic == NULL ){
|
|
fprint( "无法分配内存 %d\n" ,
|
|
sizeof(struct tagMagic)*MAGIC_magicnum);
|
|
fclose( f );
|
|
return FALSE;
|
|
}
|
|
|
|
/* 初期化*/
|
|
for( i = 0; i < MAGIC_magicnum; i ++ ) {
|
|
for( j = 0; j < MAGIC_DATAINTNUM; j ++ ) {
|
|
MAGIC_setInt( i,j,-1);
|
|
}
|
|
for( j = 0; j < MAGIC_DATACHARNUM; j ++ ) {
|
|
MAGIC_setChar( i,j,"");
|
|
}
|
|
}
|
|
|
|
/* また読み直す */
|
|
linenum = 0;
|
|
while( fgets( line, sizeof( line ), f ) ){
|
|
linenum ++;
|
|
if( line[0] == '#' )continue; /* comment */
|
|
if( line[0] == '\n' )continue; /* none */
|
|
chomp( line );
|
|
|
|
/* 行を整形する */
|
|
/* まず tab を " " に置き換える */
|
|
replaceString( line, '\t' , ' ' );
|
|
/* 先頭のスペースを取る。*/
|
|
|
|
{
|
|
char buf[256];
|
|
for( i = 0; i < strlen( line); i ++) {
|
|
if( line[i] != ' ' ) {
|
|
break;
|
|
}
|
|
strcpy( buf, &line[i]);
|
|
}
|
|
if( i != 0 ) {
|
|
strcpy( line, buf);
|
|
}
|
|
}
|
|
{
|
|
char token[256];
|
|
int ret;
|
|
|
|
#ifdef _MAGIC_OPTIMUM
|
|
if( getStringFromIndexWithDelim( line, ",", MAGIC_DATACHARNUM+MAGIC_ID+1,
|
|
token, sizeof(token)) == FALSE )
|
|
continue;
|
|
magic_readlen = atoi( token);
|
|
#endif
|
|
|
|
for( i = 0; i < MAGIC_DATACHARNUM; i ++ ) {
|
|
|
|
/* 文字列用トークンを見る */
|
|
ret = getStringFromIndexWithDelim( line,",",
|
|
i + 1,
|
|
token,sizeof(token));
|
|
if( ret==FALSE ){
|
|
fprint("文件语法错误:%s 第%d行\n",filename,linenum);
|
|
break;
|
|
}
|
|
MAGIC_setChar( magic_readlen, i, token);
|
|
}
|
|
/* 4つ目以降は数値データ */
|
|
#define MAGIC_STARTINTNUM 5
|
|
for( i = MAGIC_STARTINTNUM; i < MAGIC_DATAINTNUM+MAGIC_STARTINTNUM; i ++ ) {
|
|
ret = getStringFromIndexWithDelim( line,",",i,token,
|
|
sizeof(token));
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
|
|
if( FALSE == ret )
|
|
|
|
break;
|
|
|
|
if( 0 != strlen( token ) )
|
|
{
|
|
MAGIC_setInt( magic_readlen , i - MAGIC_STARTINTNUM , atoi( token ) );
|
|
}
|
|
|
|
#else
|
|
|
|
if( ret==FALSE ){
|
|
fprint("文件语法错误:%s 第%d行\n",filename,linenum);
|
|
break;
|
|
}
|
|
if( strlen( token) != 0 ) {
|
|
MAGIC_setInt( magic_readlen, i - MAGIC_STARTINTNUM, atoi( token));
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
|
|
if( i != MAGIC_STARTINTNUM + MAGIC_IDX && i != MAGIC_DATAINTNUM + MAGIC_STARTINTNUM )
|
|
continue;
|
|
|
|
#else
|
|
|
|
if( i < MAGIC_DATAINTNUM+MAGIC_STARTINTNUM )
|
|
continue;
|
|
|
|
#endif
|
|
/* ちょっと不細工だけどこうする */
|
|
if( MAGIC_getInt( magic_readlen, MAGIC_TARGET_DEADFLG) == 1 ) {
|
|
MAGIC_setInt( magic_readlen, MAGIC_TARGET,
|
|
MAGIC_getInt( magic_readlen, MAGIC_TARGET)+100);
|
|
}
|
|
|
|
magic_readlen ++;
|
|
}
|
|
}
|
|
fclose(f);
|
|
|
|
MAGIC_magicnum = magic_readlen;
|
|
|
|
|
|
print( "有效魔法数是 %d...", MAGIC_magicnum );
|
|
|
|
/* hash の登録 */
|
|
for( i = 0; i < arraysizeof( MAGIC_functbl); i ++ ) {
|
|
MAGIC_functbl[i].hash = hashpjw( MAGIC_functbl[i].functionname);
|
|
}
|
|
return TRUE;
|
|
}
|
|
/*------------------------------------------------------------------------
|
|
* Magicの設定ファイル読み直し
|
|
*-----------------------------------------------------------------------*/
|
|
BOOL MAGIC_reinitMagic( void )
|
|
{
|
|
freeMemory( MAGIC_magic);
|
|
return( MAGIC_initMagic( getMagicfile()));
|
|
}
|
|
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
|
|
/*------------------------------------------------------------------------
|
|
* AttMagic的初始化
|
|
*-----------------------------------------------------------------------*/
|
|
BOOL ATTMAGIC_initMagic( char *filename )
|
|
{
|
|
FILE *file;
|
|
|
|
// Open file
|
|
if( NULL == ( file = fopen( filename , "r" ) ) )
|
|
{
|
|
ATTMAGIC_magicnum = 0;
|
|
ATTMAGIC_magic = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
fseek( file , 0 , SEEK_END );
|
|
|
|
// Calculate the number of attack magics
|
|
ATTMAGIC_magicnum = ftell( file ) / sizeof( struct tagAttMagic );
|
|
if( ATTMAGIC_magicnum % 2 )
|
|
{
|
|
fprint( "打开文件失败\n" );
|
|
fclose( file );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
fseek( file , 0 , SEEK_SET );
|
|
|
|
// Allocate memory to attack magics
|
|
ATTMAGIC_magic = allocateMemory( sizeof( struct tagAttMagic ) * ATTMAGIC_magicnum );
|
|
if( NULL == ATTMAGIC_magic )
|
|
{
|
|
fprint( "无法分配内存 %d\n" , sizeof( struct tagAttMagic ) * ATTMAGIC_magicnum );
|
|
fclose( file );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Read attack magics information
|
|
memset( ATTMAGIC_magic , 0 , sizeof( struct tagAttMagic ) * ATTMAGIC_magicnum );
|
|
fread( ATTMAGIC_magic , 1 , sizeof( struct tagAttMagic ) * ATTMAGIC_magicnum , file );
|
|
|
|
fclose( file );
|
|
|
|
ATTMAGIC_magicnum = ATTMAGIC_magicnum / 2;
|
|
|
|
print( "有效的攻击魔法数 %d\n" , ATTMAGIC_magicnum );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
* AttMagic的再度初始化
|
|
*-----------------------------------------------------------------------*/
|
|
BOOL ATTMAGIC_reinitMagic( void )
|
|
{
|
|
freeMemory( ATTMAGIC_magic );
|
|
ATTMAGIC_magicnum = 0;
|
|
|
|
return ATTMAGIC_initMagic( getAttMagicfileName() );
|
|
// return ATTMAGIC_initMagic( getMagicfile() );
|
|
}
|
|
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------
|
|
* MAGIC_IDから添字を知る関数
|
|
* 返り値
|
|
* 成功: 添字
|
|
* 失敗: -1
|
|
*-----------------------------------------------------------------------*/
|
|
int MAGIC_getMagicArray( int magicid)
|
|
{
|
|
#ifdef _MAGIC_OPTIMUM
|
|
if( magicid >= 0 && magicid < MAGIC_magicnum)
|
|
return magicid;
|
|
#else
|
|
int i;
|
|
for( i = 0; i < MAGIC_magicnum; i ++ ) {
|
|
if( MAGIC_magic[i].data[MAGIC_ID] == magicid ) {
|
|
return i;
|
|
}
|
|
}
|
|
#endif
|
|
return -1;
|
|
}
|
|
/*------------------------------------------------------------
|
|
* 呪術の関数名からポインターを返す
|
|
* 引数
|
|
* name char* 呪術の名前
|
|
* 返り値
|
|
* 関数へのポインタ。ない場合にはNULL
|
|
------------------------------------------------------------*/
|
|
MAGIC_CALLFUNC MAGIC_getMagicFuncPointer(char* name)
|
|
{
|
|
int i;
|
|
int hash; //ttom
|
|
//ttom 12/18/2000
|
|
if(name==NULL) return NULL;
|
|
//ttom
|
|
//int hash = hashpjw( name );
|
|
hash=hashpjw(name);
|
|
for( i = 0 ; i< arraysizeof( MAGIC_functbl) ; i++ ) {
|
|
if( MAGIC_functbl[i].hash == hash ) {
|
|
if( strcmp( MAGIC_functbl[i].functionname, name ) == 0 ) {
|
|
return MAGIC_functbl[i].func;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Nuke start (08/23)
|
|
/*
|
|
台湾 Nuke さんのチェック。
|
|
魔法の効果範囲をチェックする。
|
|
|
|
|
|
Check the validity of the target of a magic.
|
|
Return value:
|
|
0: Valid
|
|
-1: Invalid
|
|
*/
|
|
int MAGIC_isTargetValid( int magicid, int toindex)
|
|
{
|
|
int marray;
|
|
marray= MAGIC_getMagicArray( magicid);
|
|
|
|
#ifdef _ATTACK_MAGIC
|
|
|
|
if( toindex >= 0 && toindex <= 19 )
|
|
return 0;
|
|
|
|
// One side of players
|
|
if( 20 == toindex || 21 == toindex )
|
|
{
|
|
if( MAGIC_TARGET_WHOLEOTHERSIDE == MAGIC_magic[marray].data[MAGIC_TARGET] || MAGIC_TARGET_ALL_ROWS == MAGIC_magic[marray].data[MAGIC_TARGET] )
|
|
return 0;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
// All players
|
|
if( 22 == toindex )
|
|
{
|
|
if( MAGIC_TARGET_ALL == MAGIC_magic[marray].data[MAGIC_TARGET] )
|
|
return 0;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
// One row
|
|
if( 23 == toindex || 24 == toindex || 25 == toindex || 26 == toindex )
|
|
{
|
|
if( MAGIC_TARGET_ONE_ROW == MAGIC_magic[marray].data[MAGIC_TARGET] )
|
|
return 0;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
#else
|
|
|
|
// Single player
|
|
if ((toindex >= 0x0) && (toindex <= 0x13)) return 0;
|
|
// All players
|
|
if (toindex == 0x16) {
|
|
if (MAGIC_magic[marray].data[MAGIC_TARGET] == MAGIC_TARGET_ALL)
|
|
return 0; else return -1;
|
|
}
|
|
// One side of players
|
|
if ((toindex == 0x14) || (toindex == 0x15)) {
|
|
if (MAGIC_magic[marray].data[MAGIC_TARGET] == MAGIC_TARGET_WHOLEOTHERSIDE)
|
|
return 0; else return -1;
|
|
}
|
|
|
|
#endif
|
|
|
|
// Others: Error
|
|
return -1;
|
|
}
|
|
// Nuke end
|