/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OSPRITEA.CPP //Description : Object SpriteArray #include #include #include #include #include #include #include #ifdef DEBUG #include #include //### begin alex 3/10 ###// static int num_of_unit; //#### end alex 3/10 ####// #endif //--------- Begin of function SpriteArray::SpriteArray ---------// // // initArraySize - the initial size of this array. // SpriteArray::SpriteArray(int initArraySize) : DynArrayB(sizeof(Sprite*),initArraySize, DEFAULT_REUSE_INTERVAL_DAYS) { } //----------- End of function SpriteArray::SpriteArray ---------// //--------- Begin of function SpriteArray::~SpriteArray ---------// // SpriteArray::~SpriteArray() { deinit(); } //----------- End of function SpriteArray::~SpriteArray ---------// //--------- Begin of function SpriteArray::init ---------// // void SpriteArray::init() { restart_recno = 1; } //----------- End of function SpriteArray::init ---------// //--------- Begin of function SpriteArray::deinit ---------// // // All firms should be deleted when the system terminated // // Chain : delete nation --> delete firm --> delete job --> delete item // // Some data is corrupted when the some firms still exist when // the system terminated // void SpriteArray::deinit() { if( size()==0 ) return; //----- delete sprite objects ------// Sprite* emptyPtr = NULL; Sprite* spritePtr; for( int i=1 ; i<=size() ; i++ ) { spritePtr = (Sprite*) get_ptr(i); if( spritePtr ) delete spritePtr; update( &emptyPtr, i ); // set the pointer in SpriteArray to NULL, so is_deleted() can return correct result, this is needed as Unit::deinit() will call is_deleted() } //-------- zap the array -----------// zap(); } //----------- End of function SpriteArray::deinit ---------// //--------- Begin of function SpriteArray::add ---------// void SpriteArray::add(Sprite *newSprite) { linkin(&newSprite); newSprite->sprite_recno = recno(); } //----------- End of function SpriteArray::add -----------// //--------- Begin of function SpriteArray::add_sorted ---------// // // Add the sprite into the array in a sorted order. // // spritePtr - pointer to the sprite to be added // // Note: it does not call Sprite::init_recno() as it is supposed to be used by disp_sprite_array // only and sprites to be added are existing sprites only. // // return : - the recno of the newly added sprite in SpriteArray. // void SpriteArray::add_sorted(Sprite *newSprite) { int l=0, r=size(), x=0; int addY = newSprite->abs_y2; int testY = addY + 1; //---------------------------------------------------------------------// // Use a binary search to find the right location to add the new sprite. //---------------------------------------------------------------------// while (r > l) { x = (l + r) / 2; testY = operator[](x+1)->abs_y2; // the one to be compared with the adding one. if (addY < testY) r = x; else l = x + 1; if (addY == testY) break; } if (addY >= testY) x++; insert_at(x+1, &newSprite); } //----------- End of function SpriteArray::add_sorted -----------// //--------- Begin of function SpriteArray::del ---------// void SpriteArray::del(int recNo) { Sprite* spritePtr = (Sprite*) get_ptr(recNo); err_when( !spritePtr ); delete spritePtr; linkout(recNo); } //----------- End of function SpriteArray::del -----------// //--------- Begin of function SpriteArray::process ---------// void SpriteArray::process() { #define SYS_YIELD_INTERVAL 20 Sprite* spritePtr; int arraySize = size(); if(arraySize<1) return; // no unit for process int i = restart_recno; //unit_search_node_used = 0; // reset unit_search_node_used for each process //### begin alex 3/10 ###// //int oldRecno = restart_recno; //restart_recno = 0; int newRecno = 0; //#### end alex 3/10 ####// int sysYieldCount = arraySize - arraySize%SYS_YIELD_INTERVAL; //### begin alex 3/10 ###// #ifdef DEBUG num_of_unit = 0; #endif //#### end alex 3/10 ####// for(int j=arraySize; j; --j, ++i) //for(int j=1; j<=arraySize; j++, i++) { //-------- system yield ---------// if(j==sysYieldCount) { sysYieldCount -= SYS_YIELD_INTERVAL; sys.yield(); } if(i>arraySize) i = 1; spritePtr = (Sprite*)get_ptr(i); if(!spritePtr) continue; if(spritePtr->remain_attack_delay) spritePtr->remain_attack_delay--; if(spritePtr->cur_x==-1) // cur_x == -1 if the unit has removed from the map and gone into a firm continue; //### begin alex 3/10 ###// #ifdef DEBUG num_of_unit++; #endif //#### end alex 3/10 ####// //------- process sprite --------// err_when(!spritePtr->sprite_info->need_turning && spritePtr->cur_dir!=spritePtr->final_dir); #ifdef DEBUG unsigned long profileStartTime = m.get_time(); #endif spritePtr->pre_process(); // it's actually calling Unit::pre_process() and other derived Unit classes #ifdef DEBUG unit_profile_time += m.get_time() - profileStartTime; #endif //-----------------------------------------------------// // note: for unit cur_x == -1, the unit is invisible and // no pre_process is done. // // for unit cur_x == -2, eg caravan, the unit is // invisible but pre_process is still processed. // However, sprite cur_action should be skipped. //-----------------------------------------------------// //if( spritePtr->cur_x == -1 ) if( get_ptr(i)==NULL ) // in case pre_process() kills the current Sprite continue; if(spritePtr->cur_x<0) //if( spritePtr->cur_x == -1 || spritePtr->cur_x==-2) continue; #ifdef DEBUG long startTime; #endif #ifdef DEBUG profileStartTime = m.get_time(); #endif switch(spritePtr->cur_action) { case SPRITE_IDLE: #ifdef DEBUG startTime = m.get_time(); #endif spritePtr->process_idle(); #ifdef DEBUG sprite_idle_profile_time += m.get_time() - startTime; #endif break; case SPRITE_READY_TO_MOVE: spritePtr->cur_action = SPRITE_IDLE; // to avoid problems of insensitive of mouse cursor spritePtr->process_idle(); break; case SPRITE_MOVE: #ifdef DEBUG startTime = m.get_time(); #endif spritePtr->process_move(); #ifdef DEBUG sprite_move_profile_time += m.get_time() - startTime; #endif break; case SPRITE_WAIT: #ifdef DEBUG startTime = m.get_time(); #endif spritePtr->process_wait(); #ifdef DEBUG sprite_wait_profile_time += m.get_time() - startTime; #endif break; case SPRITE_ATTACK: #ifdef DEBUG startTime = m.get_time(); #endif spritePtr->process_attack(); #ifdef DEBUG sprite_attack_profile_time += m.get_time() - startTime; #endif break; case SPRITE_TURN: spritePtr->process_turn(); break; case SPRITE_SHIP_EXTRA_MOVE: // for ship only spritePtr->process_extra_move(); break; // do nothing case SPRITE_DIE: if( spritePtr->process_die() ) { die(i); spritePtr = NULL; } break; } #ifdef DEBUG sprite_array_profile_time += m.get_time() - profileStartTime; #endif //----- can use other reasonable value to replace MIN_BACKGROUND_NODE_USED_UP ----// //### begin alex 3/10 ###// //if(!restart_recno && seek_path.total_node_availguard_count > 0) { if(++spritePtr->guard_count > GUARD_COUNT_MAX ) spritePtr->guard_count = 0; } } } //### begin alex 3/10 ###// //if(!restart_recno) // restart_recno = oldRecno; if(newRecno) restart_recno = newRecno; //#### end alex 3/10 ####// #ifdef DEBUG if(this==&unit_array || this==&bullet_array || this==&tornado_array) m.set_random_seed(m.get_random_seed() + restart_recno); #endif } //----------- End of function SpriteArray::process -----------// #ifdef DEBUG //------- Begin of function SpriteArray::operator[] -----// Sprite* SpriteArray::operator[](int recNo) { Sprite* spritePtr = (Sprite*) get_ptr(recNo); if( !spritePtr ) err.run( "SpriteArray[] is deleted" ); return spritePtr; } //--------- End of function SpriteArray::operator[] ----// #endif