Changeset 11052 for code/trunk/src/orxonox/weaponsystem/Munition.cc
- Timestamp:
- Jan 9, 2016, 6:26:20 PM (8 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
-
code/trunk/src/orxonox/weaponsystem/Munition.cc
r9667 r11052 24 24 * Fabian 'x3n' Landau 25 25 * Co-authors: 26 * ...26 * Fabien Vultier 27 27 * 28 28 */ … … 32 32 #include "core/CoreIncludes.h" 33 33 #include "core/command/Executor.h" 34 #include "core/XMLPort.h" 34 35 35 36 namespace orxonox … … 43 44 this->maxMunitionPerMagazine_ = 10; 44 45 this->maxMagazines_ = 10; 45 this->magazines_ = 10; 46 47 this->bUseSeparateMagazines_ = false; 48 this->bStackMunition_ = true; 46 this->unassignedMagazines_ = 10; 47 48 this->deployment_ = MunitionDeployment::Stack; 49 49 this->bAllowMunitionRefilling_ = true; 50 50 this->bAllowMultiMunitionRemovementUnderflow_ = true; 51 51 52 this->reloadTime_ = 0; 52 this->reloadTime_ = 0.5f; 53 54 this->lastFilledWeaponMode_ = NULL; 53 55 } 54 56 55 57 Munition::~Munition() 56 58 { 57 for (std::map<WeaponMode*, Magazine*>::iterator it = this-> currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)59 for (std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it) 58 60 delete it->second; 59 61 } 60 62 63 void Munition::XMLPort(Element& xmlelement, XMLPort::Mode mode) 64 { 65 SUPER(Munition, XMLPort, xmlelement, mode); 66 67 XMLPortParam(Munition, "initialmagazines", setNumMagazines, getNumMagazines, xmlelement, mode); 68 XMLPortParam(Munition, "maxmagazines", setMaxMagazines, getMaxMagazines, xmlelement, mode); 69 XMLPortParam(Munition, "munitionpermagazine", setMaxMunitionPerMagazine, getMaxMunitionPerMagazine, xmlelement, mode); 70 } 71 61 72 Munition::Magazine* Munition::getMagazine(WeaponMode* user) const 62 73 { 63 if ( this->bUseSeparateMagazines_)74 if (deployment_ == MunitionDeployment::Separate) 64 75 { 65 76 // For separated magazines we definitively need a given user … … 68 79 69 80 // Use the map to get the magazine assigned to the given user 70 std::map<WeaponMode*, Magazine*>::const_iterator it = this-> currentMagazines_.find(user);71 if (it != this-> currentMagazines_.end())81 std::map<WeaponMode*, Magazine*>::const_iterator it = this->assignedMagazines_.find(user); 82 if (it != this->assignedMagazines_.end()) 72 83 return it->second; 73 84 } … … 75 86 { 76 87 // We don't use separate magazines for each user, so just take the first magazine 77 if (this-> currentMagazines_.size() > 0)78 return this-> currentMagazines_.begin()->second;88 if (this->assignedMagazines_.size() > 0) 89 return this->assignedMagazines_.begin()->second; 79 90 } 80 91 … … 87 98 if (magazine) 88 99 { 89 if ( this->bStackMunition_)100 if (deployment_ == MunitionDeployment::Stack) 90 101 // With stacked munition every magazine contributes to the total amount 91 return this->maxMunitionPerMagazine_ * this-> magazines_ + magazine->munition_;102 return this->maxMunitionPerMagazine_ * this->unassignedMagazines_ + magazine->munition_; 92 103 else 93 104 // Wihtout stacked munition we just consider the current magazine … … 109 120 unsigned int Munition::getNumMagazines() const 110 121 { 111 if ( this->bStackMunition_)122 if (deployment_ == MunitionDeployment::Stack) 112 123 { 113 124 // If we stack munition and the current magazine is still full, it counts too 114 125 Magazine* magazine = this->getMagazine(0); 115 126 if (magazine && magazine->munition_ == this->maxMunitionPerMagazine_) 116 return this->magazines_ + 1; 117 } 118 119 return this->magazines_; 127 return this->unassignedMagazines_ + 1; 128 } 129 130 return this->unassignedMagazines_; 131 } 132 133 void Munition::setNumMagazines(unsigned int numMagazines) 134 { 135 this->unassignedMagazines_ = numMagazines; 120 136 } 121 137 122 138 unsigned int Munition::getMaxMunition() const 123 139 { 124 if ( this->bStackMunition_)140 if (deployment_ == MunitionDeployment::Stack) 125 141 return this->maxMunitionPerMagazine_ * this->maxMagazines_; 126 142 else … … 135 151 unsigned int munition = magazine->munition_; 136 152 137 // If we stack munition, we con't care about the current magazine - we just need enough munition in total 138 if (this->bStackMunition_) 139 munition += this->maxMunitionPerMagazine_ * this->magazines_; 153 // If we stack munition, we don't care about the current magazine - we just need enough munition in total 154 if (deployment_ == MunitionDeployment::Stack) 155 { 156 munition += this->maxMunitionPerMagazine_ * this->unassignedMagazines_; 157 } 140 158 141 159 if (munition == 0) 160 { 142 161 // Absolutely no munition - no chance to take munition 143 162 return false; 163 } 144 164 else if (this->bAllowMultiMunitionRemovementUnderflow_) 165 { 145 166 // We're not empty AND we allow underflow, so this will always work 146 167 return true; 168 } 147 169 else 170 { 148 171 // We don't allow underflow, so we have to check the amount 149 172 return (munition >= amount); 173 } 174 150 175 } 151 176 return false; … … 169 194 { 170 195 // Not enough munition 171 if ( this->bStackMunition_)196 if (deployment_ == MunitionDeployment::Stack) 172 197 { 173 198 // We stack munition, so just take what we can and then load the next magazine … … 175 200 magazine->munition_ = 0; 176 201 177 if (this->reload( 0))202 if (this->reload(NULL)) 178 203 // Successfully reloaded, continue recursively 179 204 return this->takeMunition(amount, 0); … … 199 224 { 200 225 // As long as we have enough magazines (and don't stack munition) we can reload 201 return (this-> magazines_ > 0 && !this->bStackMunition_);226 return (this->unassignedMagazines_ > 0 && deployment_ != MunitionDeployment::Stack); 202 227 } 203 228 … … 207 232 if (magazine) 208 233 { 209 if ( this->bStackMunition_)234 if (deployment_ == MunitionDeployment::Stack) 210 235 // With stacked munition, we never have to reload 211 236 return false; … … 227 252 228 253 // Check if we actually can reload 229 if (this-> magazines_ == 0)254 if (this->unassignedMagazines_ == 0) 230 255 return false; 231 256 232 257 // If we use separate magazines for each user, we definitively need a user given 233 if ( this->bUseSeparateMagazines_&& !user)258 if (deployment_ == MunitionDeployment::Separate && !user) 234 259 return false; 235 260 236 261 // If we don't use separate magazines, set user to 0 237 if (!this->bUseSeparateMagazines_) 238 user = 0; 262 if (deployment_ != MunitionDeployment::Separate) 263 { 264 user = NULL; 265 } 239 266 240 267 // Remove the current magazine for the given user 241 std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.find(user); 242 if (it != this->currentMagazines_.end()) 243 { 268 std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user); 269 if (it != this->assignedMagazines_.end()) 270 { 271 if (it->first == lastFilledWeaponMode_) 272 { 273 lastFilledWeaponMode_ = NULL; 274 } 244 275 delete it->second; 245 this-> currentMagazines_.erase(it);276 this->assignedMagazines_.erase(it); 246 277 } 247 278 248 279 // Load a new magazine 249 this-> currentMagazines_[user] = new Magazine(this, bUseReloadTime);250 this-> magazines_--;280 this->assignedMagazines_[user] = new Magazine(this, bUseReloadTime); 281 this->unassignedMagazines_--; 251 282 252 283 return true; … … 260 291 return false; 261 292 262 if ( this->bStackMunition_)293 if (deployment_ == MunitionDeployment::Stack) 263 294 { 264 295 // If we stack munition, we can always add munition until we reach the limit … … 268 299 { 269 300 // Return true if any of the current magazines is not full (loading counts as full although it returns 0 munition) 270 for (std::map<WeaponMode*, Magazine*>::const_iterator it = this-> currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)301 for (std::map<WeaponMode*, Magazine*>::const_iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it) 271 302 if (it->second->munition_ < this->maxMunitionPerMagazine_ && it->second->bLoaded_) 272 303 return true; … … 281 312 return false; 282 313 283 if ( this->bStackMunition_)314 if (deployment_ == MunitionDeployment::Stack) 284 315 { 285 316 // Stacking munition means, if a magazine gets full, the munition adds to a new magazine 286 Magazine* magazine = this->getMagazine( 0);317 Magazine* magazine = this->getMagazine(NULL); 287 318 if (magazine) 288 319 { … … 294 325 { 295 326 magazine->munition_ -= this->maxMunitionPerMagazine_; 296 this-> magazines_++;327 this->unassignedMagazines_++; 297 328 } 298 329 299 // If we reached the limit, redu ze both magazines and munition to the maximum300 if (this-> magazines_ >= this->maxMagazines_)301 { 302 this-> magazines_ = this->maxMagazines_ - 1;330 // If we reached the limit, reduce both magazines and munition to the maximum 331 if (this->unassignedMagazines_ >= this->maxMagazines_) 332 { 333 this->unassignedMagazines_ = this->maxMagazines_; 303 334 magazine->munition_ = this->maxMunitionPerMagazine_; 304 335 } … … 312 343 else 313 344 { 345 std::map<WeaponMode*, Magazine*>::iterator it; 346 347 // If the pointer to the weapon mode whose magazine got munition added to is NULL, then set the iterator to the beginning of the map 348 // Otherwise set it to the next weapon mode 349 if (lastFilledWeaponMode_ == NULL) 350 { 351 it = this->assignedMagazines_.begin(); 352 } 353 else 354 { 355 it = this->assignedMagazines_.find(lastFilledWeaponMode_); 356 ++ it; 357 } 358 314 359 // Share the munition equally to the current magazines 360 bool firstLoop = true; 315 361 while (amount > 0) 316 362 { 317 363 bool change = false; 318 for (std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)364 while (it != this->assignedMagazines_.end()) 319 365 { 320 366 // Add munition if the magazine isn't full (but only to loaded magazines) … … 323 369 it->second->munition_++; 324 370 amount--; 371 lastFilledWeaponMode_ = it->first; 325 372 change = true; 326 373 } 374 375 ++it; 327 376 } 328 377 329 378 // If there was no change in a loop, all magazines are full (or locked due to loading) 330 if (!change) 379 // Because the first loop does not start at the beginning of the map we have to treat is separately 380 if (!change && !firstLoop) 381 { 331 382 break; 383 } 384 385 it = this->assignedMagazines_.begin(); 386 firstLoop = false; 332 387 } 333 388 … … 340 395 // TODO: 'amount' is not used 341 396 342 if ( this->bStackMunition_)397 if (deployment_ == MunitionDeployment::Stack) 343 398 // If we stack munition, we can always add new magazines because they contribute directly to the munition 344 399 return (this->getNumMunition(0) < this->getMaxMunition()); 345 400 else 346 401 // If we don't stack munition, we're more limited 347 return ((this->currentMagazines_.size() + this->magazines_) < this->maxMagazines_); 348 } 349 350 bool Munition::addMagazines(unsigned int amount) 351 { 402 return ((this->assignedMagazines_.size() + this->unassignedMagazines_) < this->maxMagazines_); 403 } 404 405 unsigned int Munition::addMagazines(unsigned int amount) 406 { 407 unsigned int addedMagazines = 0; 408 352 409 if (!this->canAddMagazines(amount)) 353 return false;410 return 0; 354 411 355 412 // Calculate how many magazines are needed 356 int needed_magazines = this->maxMagazines_ - this-> magazines_ - this->currentMagazines_.size();413 int needed_magazines = this->maxMagazines_ - this->unassignedMagazines_ - this->assignedMagazines_.size(); 357 414 358 415 // If zero or less magazines are needed, we definitively don't need more magazines (unless we stack munition - then a magazine contributes directly to the munition) 359 if (needed_magazines <= 0 && !this->bStackMunition_)360 return false;416 if (needed_magazines <= 0 && deployment_ != MunitionDeployment::Stack) 417 return 0; 361 418 362 419 if (amount <= static_cast<unsigned int>(needed_magazines)) 363 420 { 364 421 // We need more magazines than we get, so just add them 365 this->magazines_ += amount; 422 this->unassignedMagazines_ += amount; 423 addedMagazines = amount; 366 424 } 367 425 else 368 426 { 369 427 // We get more magazines than we need, so just add the needed amount 370 this->magazines_ += needed_magazines; 371 if (this->bStackMunition_) 428 this->unassignedMagazines_ += needed_magazines; 429 addedMagazines = needed_magazines; 430 if (deployment_ == MunitionDeployment::Stack) 372 431 { 373 432 // We stack munition, so the additional amount contributes directly to the munition of the current magazine … … 378 437 } 379 438 380 return true; 439 // Reload as many empty magazines as possible 440 // Double loop and break is needed because the reload function changes the assigned magazines. This may confuse the iterator. 441 for (unsigned int i = 0; i < addedMagazines; ++i) 442 { 443 for (std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it) 444 { 445 if (needReload(it->first)) 446 { 447 reload(it->first); 448 break; 449 } 450 } 451 } 452 453 return addedMagazines; 381 454 } 382 455 383 456 bool Munition::canRemoveMagazines(unsigned int amount) const 384 457 { 385 if ( this->bStackMunition_)386 { 387 if (this-> magazines_ >= amount)458 if (deployment_ == MunitionDeployment::Stack) 459 { 460 if (this->unassignedMagazines_ >= amount) 388 461 { 389 462 // We have enough magazines 390 463 return true; 391 464 } 392 else if (this-> magazines_ == amount - 1)465 else if (this->unassignedMagazines_ == amount - 1) 393 466 { 394 467 // We lack one magazine, check if the current magazine is still full, if yes we're fine … … 406 479 { 407 480 // In case we're not stacking munition, just check the number of magazines 408 return (this-> magazines_ >= amount);481 return (this->unassignedMagazines_ >= amount); 409 482 } 410 483 … … 417 490 return false; 418 491 419 if (this-> magazines_ >= amount)492 if (this->unassignedMagazines_ >= amount) 420 493 { 421 494 // We have enough magazines, just remove the amount 422 this-> magazines_ -= amount;423 } 424 else if ( this->bStackMunition_)495 this->unassignedMagazines_ -= amount; 496 } 497 else if (deployment_ == MunitionDeployment::Stack) 425 498 { 426 499 // We don't have enough magazines, but we're stacking munition, so additionally remove the bullets from the current magazine 427 this-> magazines_ = 0;500 this->unassignedMagazines_ = 0; 428 501 Magazine* magazine = this->getMagazine(0); 429 502 if (magazine) … … 437 510 { 438 511 // If we use separate magazines, we need a user 439 if ( this->bUseSeparateMagazines_&& !user)512 if (deployment_ == MunitionDeployment::Separate && !user) 440 513 return false; 441 514 442 515 // If we don't use separate magazines, set user to 0 443 if ( !this->bUseSeparateMagazines_)444 user = 0;516 if (deployment_ != MunitionDeployment::Separate) 517 user = NULL; 445 518 446 519 // Remove the current magazine for the given user 447 std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.find(user); 448 if (it != this->currentMagazines_.end()) 449 { 520 std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user); 521 if (it != this->assignedMagazines_.end()) 522 { 523 if (it->first == lastFilledWeaponMode_) 524 { 525 lastFilledWeaponMode_ = NULL; 526 } 450 527 delete it->second; 451 this-> currentMagazines_.erase(it);528 this->assignedMagazines_.erase(it); 452 529 return true; 453 530 } … … 465 542 this->bLoaded_ = false; 466 543 467 if (bUseReloadTime && munition->reloadTime_ > 0 && !munition->bStackMunition_)544 if (bUseReloadTime && munition->reloadTime_ > 0 && munition->deployment_ != MunitionDeployment::Stack) 468 545 { 469 546 const ExecutorPtr& executor = createExecutor(createFunctor(&Magazine::loaded, this));
Note: See TracChangeset
for help on using the changeset viewer.