1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3
4 This file is part of Aquaria.
5
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "../BBGE/Gradient.h"
22 #include "../BBGE/AfterEffect.h"
23 #include "../BBGE/MathFunctions.h"
24 #include "../BBGE/DebugFont.h"
25 #include "../BBGE/LensFlare.h"
26 #include "../BBGE/RoundedRect.h"
27 #include "../BBGE/SimpleIStringStream.h"
28
29 #include "Game.h"
30 #include "GridRender.h"
31 #include "WaterSurfaceRender.h"
32 #include "ScriptedEntity.h"
33 #include "AutoMap.h"
34 #include "FlockEntity.h"
35 #include "SchoolFish.h"
36 #include "Avatar.h"
37 #include "Shot.h"
38 #include "Web.h"
39 #include "StatsAndAchievements.h"
40
41 #include "ToolTip.h"
42
43 std::vector<std::string> allowedMaps;
44
45 Vector worldLeftCenter(217,250), worldRightCenter(575, 250);
46 Vector opt_save_original = Vector(350, 350), opt_cancel_original = Vector(450, 350);
47
48 const float bgSfxVol = 1.0;
49
50 const float MENUPAGETRANSTIME = 0.2; // 0.2
51
52 const int foodPageSize = 16;
53 const int treasurePageSize = 16;
54
55 int FoodSlot::foodSlotIndex = -1;
56
57 int selectedTreasureFlag = -1;
58
59 std::vector<FoodHolder*> foodHolders;
60 std::vector<PetSlot*> petSlots;
61
62
getSceneFilename(const std::string & scene)63 std::string getSceneFilename(const std::string &scene)
64 {
65 if (dsq->mod.isActive())
66 return std::string(dsq->mod.getPath() + "maps/" + scene + ".xml");
67 else
68 return std::string("data/maps/"+scene+".xml");
69 return "";
70 }
71
PetSlot(int pet)72 PetSlot::PetSlot(int pet) : AquariaGuiQuad()
73 {
74 PetData *p = dsq->continuity.getPetData(pet);
75 if (p)
76 {
77 std::string fn = "collectibles/egg-" + p->namePart;
78 setTexture(fn);
79 }
80 scale = Vector(0.9, 0.9);
81 petidx = pet;
82 mouseDown = false;
83 petFlag = FLAG_PET_NAMESTART + petidx;
84 wasSlot = false;
85 }
86
onUpdate(float dt)87 void PetSlot::onUpdate(float dt)
88 {
89 AquariaGuiQuad::onUpdate(dt);
90
91 if (!dsq->continuity.getFlag(petFlag))
92 {
93 if (!wasSlot)
94 {
95 setTexture("gui/wok");
96 setWidthHeight(80);
97 wasSlot = true;
98 }
99 //alphaMod = 0;
100 return;
101 }
102 else
103 {
104 alphaMod = 1;
105
106 if (wasSlot)
107 {
108 PetData *p = dsq->continuity.getPetData(petidx);
109 if (p)
110 {
111 std::string fn = "collectibles/egg-" + p->namePart;
112 setTexture(fn);
113 }
114 wasSlot = false;
115 }
116 }
117
118 if (dsq->continuity.getFlag(FLAG_PET_ACTIVE) == petFlag)
119 {
120 color = Vector(1,1,1);
121 }
122 else
123 color = Vector(0.5, 0.5, 0.5);
124
125 if (alpha.x < 1) return;
126
127 if ((core->mouse.position - getWorldPosition()).isLength2DIn(32))
128 {
129 scale.interpolateTo(Vector(1.2, 1.2), 0.1);
130
131 if (core->mouse.buttons.left && !mouseDown)
132 {
133 mouseDown = true;
134 }
135 else if (!core->mouse.buttons.left && mouseDown)
136 {
137 dsq->sound->playSfx("click");
138
139 if (dsq->continuity.getFlag(FLAG_PET_ACTIVE) == petFlag)
140 {
141 dsq->game->setActivePet(0);
142 dsq->sound->playSfx("pet-on");
143 }
144 else
145 {
146 dsq->game->setActivePet(FLAG_PET_NAMESTART + petidx);
147 dsq->sound->playSfx("pet-off");
148 }
149 mouseDown = false;
150 }
151 }
152 else
153 {
154 mouseDown = false;
155 scale.interpolateTo(Vector(0.9, 0.9), 0.1);
156 }
157 }
158
FoodHolder(int slot,bool trash)159 FoodHolder::FoodHolder(int slot, bool trash) : Quad(), slot(slot), trash(trash)
160 {
161 foodHolderIngredient = 0;
162 buttonDown = false;
163
164 //setTexture("Gui/wok");
165 renderQuad = false;
166
167 wok = new Quad;
168 if (trash)
169 wok->setTexture("gui/wok-drop");
170 else
171 wok->setTexture("gui/wok");
172 addChild(wok, PM_POINTER, RBP_ON);
173
174 ing = new Quad;
175 ing->renderQuad = false;
176 addChild(ing, PM_POINTER);
177
178 lid = new Quad("gui/wok-lid", Vector(0,0));
179 lid->alpha = 0;
180 lid->alphaMod = 0.5;
181 addChild(lid, PM_POINTER);
182 }
183
animateLid(bool down,bool longAnim)184 void FoodHolder::animateLid(bool down, bool longAnim)
185 {
186 float t = 0.2;
187
188 if (!longAnim)
189 {
190 t = 0.1;
191 }
192
193 if (down)
194 {
195 dsq->sound->playSfx("bubble-lid");
196 lid->alpha.interpolateTo(1, t);
197 dsq->main(t);
198 }
199 else
200 {
201 lid->alpha.interpolateTo(0, t);
202 }
203 }
204
isTrash()205 bool FoodHolder::isTrash()
206 {
207 return trash;
208 }
209
isEmpty()210 bool FoodHolder::isEmpty()
211 {
212 return (foodHolderIngredient == 0);
213 }
214
getIngredient()215 IngredientData *FoodHolder::getIngredient()
216 {
217 return foodHolderIngredient;
218 }
219
setIngredient(IngredientData * i,bool effects)220 void FoodHolder::setIngredient(IngredientData *i, bool effects)
221 {
222 IngredientData *oldi = foodHolderIngredient;
223 foodHolderIngredient = i;
224
225 if (oldi) {
226 if (oldi->held > 0)
227 oldi->held --;
228 oldi->amount ++;
229 }
230
231 if (!i)
232 {
233 //ing->scale.interpolateTo(Vector(0,0), 0.1);
234 ing->renderQuad = false;
235 //setTexture("Gui/wok");
236 if (oldi && effects)
237 {
238 core->sound->playSfx("Drop");
239 }
240
241 game->enqueuePreviewRecipe();
242 }
243 else
244 {
245 i->held ++;
246 if (i->amount > 0)
247 i->amount --;
248
249 ing->setTexture("Ingredients/" + i->gfx);
250 ing->renderQuad = true;
251 if (effects)
252 {
253 core->sound->playSfx("Wok");
254
255 ing->scale.ensureData();
256 ing->scale.data->path.clear();
257 ing->scale.data->path.addPathNode(Vector(1,1),0);
258 ing->scale.data->path.addPathNode(Vector(1.25,1.25), 0.2);
259 ing->scale.data->path.addPathNode(Vector(1,1),1);
260 ing->scale.startPath(0.5);
261 }
262
263 game->enqueuePreviewRecipe();
264 }
265 }
266
enqueuePreviewRecipe()267 void Game::enqueuePreviewRecipe()
268 {
269 enqueuedPreviewRecipe = 1;
270 }
271
updatePreviewRecipe()272 void Game::updatePreviewRecipe()
273 {
274 const float t = 0.2;
275
276 updateCookList();
277
278 if (cookList.size() < 2 || recipeMenu.on){
279 previewRecipe->alpha.interpolateTo(0, t);
280 }
281 else{
282 Recipe *r = findRecipe(cookList);
283
284 IngredientData *data=0;
285
286 if (r && r->isKnown())
287 {
288 data = dsq->continuity.getIngredientDataByName(r->result);
289 previewRecipe->setTexture("ingredients/"+data->gfx);
290 }
291 else
292 {
293 previewRecipe->setTexture("gui/question-mark");
294 }
295
296 previewRecipe->alpha.interpolateTo(1, t);
297
298 }
299 }
300
dropFood()301 void FoodHolder::dropFood()
302 {
303 if (foodHolderIngredient)
304 {
305 setIngredient(0);
306 dsq->game->refreshFoodSlots(true);
307 }
308 }
309
onUpdate(float dt)310 void FoodHolder::onUpdate(float dt)
311 {
312 Quad::onUpdate(dt);
313
314 if (!dsq->game->recipeMenu.on && foodHolderIngredient)
315 {
316 if ((core->mouse.position - getWorldPosition()).isLength2DIn(20))
317 {
318 if (!buttonDown && core->mouse.buttons.left)
319 {
320 dropFood();
321 buttonDown = true;
322 }
323 }
324
325 if (!buttonDown && core->mouse.buttons.left)
326 buttonDown = true;
327 if (buttonDown && !core->mouse.buttons.left)
328 buttonDown = false;
329 }
330 }
331
FoodSlot(int slot)332 FoodSlot::FoodSlot(int slot) : AquariaGuiQuad(), slot(slot)
333 {
334 doubleClickDelay = 0;
335
336 right = false;
337
338 renderQuad = false;
339
340 label = new DebugFont(8, "");
341 label->position = Vector(-2, 9);
342 addChild(label, PM_POINTER);
343
344 inCookSlot = false;
345
346 ingredient = 0;
347
348 lastIngredient = 0;
349 lastAmount = 0;
350
351 grabTime = 0;
352
353 foodSlotIndex = -1;
354 scaleFactor = 1;
355
356 shareAlphaWithChildren = 1;
357
358 rmb = 0;
359
360 }
361
setOriginalPosition(const Vector & op)362 void FoodSlot::setOriginalPosition(const Vector &op)
363 {
364 originalPosition = op;
365 }
366
toggle(bool f)367 void FoodSlot::toggle(bool f)
368 {
369 if (f)
370 {
371 alpha = 1;
372 alphaMod = 1;
373 label->alpha = 1;
374 }
375 else
376 {
377 alpha = 0;
378 alphaMod = 0;
379 label->alpha = 0;
380 }
381 }
382
refresh(bool effects)383 void FoodSlot::refresh(bool effects)
384 {
385 int offset = game->currentFoodPage*foodPageSize;
386 IngredientData *i = dsq->continuity.getIngredientHeldByIndex(offset+slot);
387 if (i)
388 {
389 ingredient = i;
390
391 if (i->amount > 0)
392 {
393 std::ostringstream os;
394 if (i->amount > 1)
395 os << i->amount << "/" << i->maxAmount;
396 label->setText(os.str());
397 setTexture("Ingredients/" + i->gfx);
398 renderQuad = true;
399 }
400 else
401 {
402 label->setText("");
403 renderQuad = true;
404
405 setTexture("gui/wok");
406 setWidthHeight(64);
407 }
408 }
409 else
410 {
411 ingredient = 0;
412
413 label->setText("");
414 renderQuad = true;
415 setTexture("gui/wok");
416 setWidthHeight(64);
417 }
418
419 scale.interpolateTo(Vector(1,1)*scaleFactor,0.001);
420
421 if (ingredient != 0 && (i != lastIngredient || (i && i->amount != lastAmount)))
422 {
423 if (effects)
424 {
425 scale.ensureData();
426 scale.data->path.clear();
427 scale.data->path.addPathNode(Vector(1,1)*scaleFactor,0);
428 scale.data->path.addPathNode(Vector(1.5,1.5)*scaleFactor, 0.2);
429 scale.data->path.addPathNode(Vector(1,1)*scaleFactor,1);
430 scale.startPath(0.5);
431 }
432 }
433
434 lastIngredient = i;
435 if (i)
436 lastAmount = i->amount;
437 else
438 lastAmount = 0;
439 }
440
eatMe()441 void FoodSlot::eatMe()
442 {
443 if (ingredient && !dsq->isNested())
444 {
445 for (int i = 0; i < foodHolders.size(); i++)
446 {
447 if (!foodHolders[i]->isTrash() && !foodHolders[i]->isEmpty())
448 {
449 dsq->sound->playSfx("denied");
450 foodHolders[i]->dropFood();
451 return;
452 }
453 }
454
455 if (!ingredient->effects.empty())
456 {
457 bool eaten = dsq->continuity.applyIngredientEffects(ingredient);
458 if(eaten)
459 {
460 ingredient->amount--;
461 dsq->continuity.removeEmptyIngredients();
462 dsq->game->refreshFoodSlots(true);
463 }
464 }
465 else
466 {
467 dsq->sound->playSfx("denied");
468 /// don't
469 }
470 }
471 }
472
moveRight()473 void FoodSlot::moveRight()
474 {
475 if (!ingredient) return;
476 if (ingredient->amount <= 0) return;
477
478 for (int i = foodHolders.size()-1; i >= 0; i--)
479 {
480 if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash())
481 {
482 foodHolders[i]->setIngredient(ingredient);
483 inCookSlot = true;
484 refresh(true);
485 break;
486 }
487 }
488 }
489
discard()490 void FoodSlot::discard()
491 {
492 if (!ingredient) return;
493 if (ingredient->amount <= 0) return;
494
495 ingredient->amount--;
496 dsq->game->dropIngrNames.push_back(ingredient->name);
497 dsq->continuity.removeEmptyIngredients();
498 dsq->game->refreshFoodSlots(true);
499 }
500
isCursorIn()501 bool FoodSlot::isCursorIn()
502 {
503 return (core->mouse.position - getWorldPosition()).isLength2DIn(32);
504 }
505
onUpdate(float dt)506 void FoodSlot::onUpdate(float dt)
507 {
508 AquariaGuiQuad::onUpdate(dt);
509
510 if (doubleClickDelay > 0)
511 {
512 doubleClickDelay -= dt;
513 if (doubleClickDelay < 0) doubleClickDelay = 0;
514 }
515
516 if (alphaMod==1 && ingredient && ingredient->amount > 0)
517 {
518 if (foodSlotIndex == slot)
519 {
520 //grabTime += dt;
521 if (!core->mouse.buttons.left)
522 {
523 foodSlotIndex = -1;
524
525 //if (ingredient->type < IT_FOOD)
526
527 //if (grabTime > 0.5f)
528 if (!dsq->game->recipeMenu.on)
529 {
530 /*
531 dsq->game->removeRenderObject(this);
532 dsq->game->addRenderObject(this, LR_MENU);
533 */
534
535
536 Vector wp = getWorldPosition();
537 if ((dsq->game->lips->getWorldPosition() - wp).isLength2DIn(32))
538 {
539 dsq->menuSelectDelay = 0.5;
540
541 eatMe();
542 }
543 else if (wp.x < 40 || wp.y < 40 || wp.x > 760 || wp.y > 560)
544 {
545 discard();
546 }
547 else
548 {
549 bool droppedIn = false;
550 for (int i = 0; i < foodHolders.size(); i++)
551 {
552 bool in = (foodHolders[i]->getWorldPosition() - wp).isLength2DIn(32);
553 if (in)
554 {
555 droppedIn = true;
556
557 if (foodHolders[i]->isTrash())
558 {
559 discard();
560
561 dsq->game->foodLabel->alpha.interpolateTo(0, 2);
562 dsq->game->foodDescription->alpha.interpolateTo(0, 2);
563
564 break;
565 //return;
566 }
567 else if (foodHolders[i]->isEmpty())
568 {
569 foodHolders[i]->setIngredient(ingredient);
570 inCookSlot = true;
571 refresh(true);
572 break;
573 }
574 }
575 }
576
577 if (!droppedIn)
578 {
579 if (doubleClickDelay > 0)
580 {
581 dsq->menuSelectDelay = 0.5;
582 doubleClickDelay = 0;
583 eatMe();
584
585 //if (!originalPosition.isZero())
586 position = originalPosition;
587
588 label->alpha = 1;
589 grabTime = 0;
590
591 return;
592 }
593 else
594 {
595 doubleClickDelay = DOUBLE_CLICK_DELAY;
596 }
597 }
598 }
599 }
600 /*
601 else
602 {
603 if (ingredient)
604 debugLog(splitCamelCase(ingredient->name));
605 }
606 */
607
608 //if (!originalPosition.isZero())
609 position = originalPosition;
610
611 label->alpha = 1;
612
613 grabTime = 0;
614 }
615 else
616 {
617 if (!dsq->game->recipeMenu.on)
618 {
619 if (dsq->inputMode == INPUT_MOUSE)
620 {
621 Vector diff = core->mouse.position - getWorldPosition();
622 position += diff;
623 dsq->game->moveFoodSlotToFront = this;
624 }
625 }
626 //position = parent->getWorldCollidePosition(core->mouse.position);
627 //position = core->mouse.position;
628 }
629 }
630
631 if ((core->mouse.position - getWorldPosition()).isLength2DIn(16))
632 //if (isCursorIn())
633 {
634 dsq->game->foodLabel->setText(ingredient->displayName);
635 dsq->game->foodLabel->alpha.interpolateTo(1, 0.2);
636
637 dsq->game->foodDescription->setText(dsq->continuity.getIngredientAffectsString(ingredient));
638 dsq->game->foodDescription->alpha.interpolateTo(1, 0.2);
639
640 if (core->mouse.buttons.left && foodSlotIndex == -1)
641 {
642 grabTime = 0;
643 foodSlotIndex = slot;
644 label->alpha = 0;
645
646 /*
647 dsq->game->removeRenderObject(this);
648 dsq->game->addRenderObject(this, LR_HUD);
649 */
650
651 if (!inCookSlot)
652 {
653 originalPosition = position;
654 }
655 }
656
657 if (core->mouse.buttons.right && !rmb)
658 {
659 rmb = 1;
660 }
661 else if (!core->mouse.buttons.right && rmb)
662 {
663 rmb = 0;
664 if (!game->recipeMenu.on)
665 moveRight();
666 return;
667 }
668
669 /*
670 if (core->mouse.buttons.right && !right)
671 {
672 right = true;
673 }
674 else if (!core->mouse.buttons.right && right)
675 {
676 right = false;
677
678 bool dropped = false;
679 for (int i = foodHolders.size()-1; i >= 0; i--)
680 {
681 if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash())
682 {
683 foodHolders[i]->setIngredient(ingredient);
684 inCookSlot = true;
685 refresh();
686 dropped = true;
687 break;
688 }
689 }
690
691 if (dropped)
692 {
693 }
694 else
695 {
696 core->sound->playSfx("denied");
697 }
698 }
699 */
700 }
701 else
702 {
703 if (!dsq->game->foodLabel->alpha.isInterpolating())
704 dsq->game->foodLabel->alpha.interpolateTo(0, 2);
705 if (!dsq->game->foodDescription->alpha.isInterpolating())
706 dsq->game->foodDescription->alpha.interpolateTo(0, 2);
707 rmb = 0;
708 }
709 }
710 else
711 {
712 rmb = 0;
713 }
714 }
715
SongSlot(int songSlot)716 SongSlot::SongSlot(int songSlot) : AquariaGuiQuad(), songSlot(songSlot)
717 {
718 songType = dsq->continuity.getSongTypeBySlot(songSlot);
719 std::ostringstream os;
720 os << "Song/SongSlot-" << songSlot;
721 setTexture(os.str());
722
723 glow = new Quad("particles/glow", Vector(0,0));
724 glow->setWidthHeight(128, 128);
725 glow->setBlendType(RenderObject::BLEND_ADD);
726 glow->alpha = 0;
727 addChild(glow, PM_POINTER);
728
729 mbDown = false;
730
731 if (dsq->continuity.isSongTypeForm((SongType)dsq->continuity.getSongTypeBySlot(songSlot)))
732 scale = Vector(0.9, 0.9);
733 else
734 scale = Vector(0.6, 0.6);
735 }
736
onUpdate(float dt)737 void SongSlot::onUpdate(float dt)
738 {
739 AquariaGuiQuad::onUpdate(dt);
740
741 if (alpha.x == 1 && alphaMod == 1 && (!parent || parent->alpha.x == 1))
742 {
743 if ((core->mouse.position - getWorldPosition()).isLength2DIn(24))
744 {
745 dsq->game->playSongInMenu(songType);
746 dsq->game->songLabel->setText(dsq->continuity.getSongNameBySlot(songSlot));
747 dsq->game->songLabel->alpha.interpolateTo(1, 0.2);
748 const bool anyButton = core->mouse.buttons.left || core->mouse.buttons.right;
749 if (!mbDown && anyButton)
750 {
751 mbDown = true;
752 }
753 else if (mbDown && !anyButton)
754 {
755 mbDown = false;
756
757 dsq->game->playSongInMenu(songType, 1);
758 if (!dsq->sound->isPlayingVoice())
759 dsq->voice(dsq->continuity.getVoxForSongSlot(songSlot));
760 //dsq->game->songDescription->setText(dsq->continuity.getDescriptionForSongSlot(songSlot));
761
762 }
763 glow->alpha.interpolateTo(0.2, 0.15);
764 }
765 else
766 {
767 mbDown = false;
768 glow->alpha.interpolateTo(0, 0.2);
769 if (!dsq->game->songLabel->alpha.isInterpolating())
770 {
771 dsq->game->songLabel->alpha.interpolateTo(0, 2);
772 /*
773 dsq->game->songLabel->alpha.path.addPathNode(dsq->game->songLabel->alpha, 0);
774 dsq->game->songLabel->alpha.path.addPathNode(dsq->game->songLabel->alpha, 0.5);
775 dsq->game->songLabel->alpha.path.addPathNode(0, 1);
776 dsq->game->songLabel->alpha.startPath(3);
777 */
778 }
779 }
780 }
781 }
782
783 const int treasureFlagStart = 500;
784
TreasureSlot(int index)785 TreasureSlot::TreasureSlot(int index) : AquariaGuiQuad()
786 {
787 this->index = index;
788 mbd = false;
789 flag = 0;
790 doubleClickTimer = 0;
791 }
792
onUpdate(float dt)793 void TreasureSlot::onUpdate(float dt)
794 {
795 AquariaGuiQuad::onUpdate(dt);
796
797 doubleClickTimer -= dt;
798 if (doubleClickTimer < 0)
799 doubleClickTimer = 0;
800
801 if (alphaMod == 1 && alpha.x == 1 && flag != 0)
802 {
803 if ((core->mouse.position - getWorldPosition()).isLength2DIn(18))
804 {
805 scale.interpolateTo(Vector(1.2, 1.2), 0.1);
806 if (core->mouse.buttons.left && !mbd)
807 {
808 mbd = true;
809 }
810 else if (!core->mouse.buttons.left && mbd)
811 {
812 mbd = false;
813
814 if (doubleClickTimer > 0)
815 {
816 doubleClickTimer = 0;
817
818 dsq->game->onUseTreasure(flag);
819 }
820 else
821 {
822 dsq->sound->playSfx("treasure-select", 0.5);
823 dsq->spawnParticleEffect("menu-switch", worldRightCenter, 0, 0, LR_HUD3, 1);
824
825
826
827 dsq->game->treasureLabel->setText(treasureName);
828 dsq->game->treasureLabel->alpha = 1;
829 dsq->game->treasureCloseUp->setTexture(dsq->continuity.treasureData[flag].gfx);
830 //dsq->game->treasureCloseUp->scale = Vector(dsq->continuity.treasureData[flag].sz, dsq->continuity.treasureData[flag].sz);
831
832 dsq->game->treasureCloseUp->alpha = 1;
833
834 dsq->game->treasureDescription->setText(treasureDesc, Vector(400,450), 400);
835 dsq->game->treasureDescription->alpha = 1;
836
837 dsq->game->use->alpha = dsq->continuity.treasureData[flag].use;
838
839 /*
840 dsq->game->treasureCloseUp->scale = Vector(0.5,0.5);
841 dsq->game->treasureCloseUp->scale.interpolateTo(Vector(1,1), 0.2);
842 dsq->game->treasureCloseUp->alpha = 0.1;
843 dsq->game->treasureCloseUp->alpha.interpolateTo(1, 0.2);
844 */
845
846 selectedTreasureFlag = flag;
847
848 doubleClickTimer = 0.2;
849
850
851 std::ostringstream os;
852 os << "treasure flag: " << flag << " desc: " << treasureDesc;
853 debugLog(os.str());
854 }
855 }
856 }
857 else
858 {
859 mbd = false;
860 scale.interpolateTo(Vector(1, 1), 0.1);
861 }
862 }
863 else
864 {
865 mbd = false;
866 scale.interpolateTo(Vector(1, 1), 0.001);
867 }
868 }
869
refresh()870 void TreasureSlot::refresh()
871 {
872 flag = (game->currentTreasurePage*treasurePageSize) + index + treasureFlagStart;
873 if (flag >= FLAG_COLLECTIBLE_START && flag < FLAG_COLLECTIBLE_END && dsq->continuity.getFlag(flag)>0)
874 {
875 // get treasure image somehow
876 setTexture(dsq->continuity.treasureData[flag].gfx);
877 float scl = dsq->continuity.treasureData[flag].sz;
878
879 float w = width;
880 float h = height;
881 float sz = 50;
882 if (w > h)
883 {
884 w = sz;
885 h = (height*sz)/width;
886 }
887 else
888 {
889 h = sz;
890 w = (width*sz)/height;
891 }
892
893 setWidthHeight(w*scl, h*scl);
894
895 std::string parse = dsq->continuity.stringBank.get(flag);
896
897 int p1 = parse.find_first_of('[');
898 if (p1 != std::string::npos)
899 {
900 p1++;
901 int p2 = parse.find_first_of(']');
902 treasureName = parse.substr(p1,p2-p1);
903
904 p1 = parse.find_last_of('[');
905 if (p1 != std::string::npos)
906 {
907 p1++;
908 p2 = parse.find_last_of(']');
909 treasureDesc = parse.substr(p1,p2-p1);
910 }
911 }
912
913 alphaMod = 1;
914 }
915 else
916 {
917 flag = 0;
918 alphaMod = 1;
919
920 setTexture("gui/wok");
921 setWidthHeight(48);
922 //alphaMod = 0;
923 }
924 }
925
getNearestIngredient(const Vector & pos,int radius)926 Ingredient *Game::getNearestIngredient(const Vector &pos, int radius)
927 {
928 int closest = -1;
929 int r2 = sqr(radius);
930 Ingredient *returnIngredient = 0;
931
932 for (Ingredients::iterator i = ingredients.begin(); i != ingredients.end(); i++)
933 {
934 int len = (pos - (*i)->position).getSquaredLength2D();
935 if (len <= r2 && (closest == - 1 || len < closest))
936 {
937 closest = len;
938 returnIngredient = (*i);
939 }
940 }
941 return returnIngredient;
942 }
943
getNearestEntity(const Vector & pos,int radius,Entity * ignore,EntityType et,DamageType dt,int lrStart,int lrEnd)944 Entity *Game::getNearestEntity(const Vector &pos, int radius, Entity *ignore, EntityType et, DamageType dt, int lrStart, int lrEnd)
945 {
946 int sqrRadius = radius*radius;
947 Entity *closest = 0;
948 int sml=-1;
949 int dist = 0;
950 FOR_ENTITIES(i)
951 {
952 Entity *e = *i;
953 dist = (e->position - pos).getSquaredLength2D();
954 if (dist <= sqrRadius)
955 {
956 if (e != ignore && e->isPresent())
957 {
958 if (lrStart == -1 || lrEnd == -1 || (e->layer >= lrStart && e->layer <= lrEnd))
959 {
960 if (et == ET_NOTYPE || e->getEntityType() == et)
961 {
962 if (dt == DT_NONE || e->isDamageTarget(dt))
963 {
964 if (sml == -1 || dist < sml)
965 {
966 closest = e;
967 sml = dist;
968 }
969 }
970 }
971 }
972 }
973 }
974 }
975 return closest;
976 }
977
978 /*
979 class Avatar : public Entity
980 {
981 public:
982 Vector position, myZoom;
983 void clampPosition();
984 Entity *convoEntity;
985 std::string convoToRun;
986 Entity *attachedTo;
987 Quad *burstBar;
988 int health;
989 bool isCharging();
990 bool isEntityDead();
991 int maxHealth, mana, maxMana;
992 bool zoomOverriden;
993
994 };
995 */
996
997 /*
998 #include "JetStream.h"
999 #include "Rock.h"
1000 #include "SchoolFish.h"
1001 */
1002 /*
1003 #include "Game.h"
1004 #include "AfterEffect.h"
1005 #include "Button.h"
1006 #include "TextBox.h"
1007 #include "LightShaft.h"
1008 #include "Item.h"
1009
1010 #include "Elements.h"
1011 #include "WavyWeed.h"
1012 #include "BitmapFont.h"
1013
1014 #include "ParticleEffects.h"
1015
1016
1017
1018 // SPECIAL
1019 */
1020
1021 Vector menuBgScale;
1022
1023 const int ITEMS_PER_PAGE = 12;
1024
ObsRow(int tx,int ty,int len)1025 ObsRow::ObsRow(int tx, int ty, int len) : tx(tx), ty(ty), len(len)
1026 {
1027 }
1028
getNumberOfEntitiesNamed(const std::string & name)1029 int Game::getNumberOfEntitiesNamed(const std::string &name)
1030 {
1031 int c = 0;
1032 FOR_ENTITIES(i)
1033 {
1034 Entity *e = *i;
1035 if (e->life == 1 && (nocasecmp(e->name, name)==0))
1036 c++;
1037 }
1038 return c;
1039 }
1040
playSongInMenu(int songType,bool override)1041 void Game::playSongInMenu(int songType, bool override)
1042 {
1043 if (playingSongInMenu == -1 || override)
1044 {
1045 playingSongInMenu = songType;
1046 currentSongMenuNote = 0;
1047 songMenuPlayDelay = 0.5;
1048 }
1049 }
1050
flipRenderObjectVertical(RenderObject * r,int flipY)1051 void Game::flipRenderObjectVertical(RenderObject *r, int flipY)
1052 {
1053 if (r->position.y < flipY)
1054 r->position.y = flipY + (flipY-r->position.y);
1055 else
1056 r->position.y = flipY - (r->position.y-flipY);
1057 }
1058
isSceneFlipped()1059 bool Game::isSceneFlipped()
1060 {
1061 return sceneFlipped;
1062 }
1063
flipSceneVertical(int flipY)1064 void Game::flipSceneVertical(int flipY)
1065 {
1066 sceneFlipped = !sceneFlipped;
1067 dsq->screenTransition->capture();
1068 dsq->render();
1069 dsq->screenTransition->go(1);
1070
1071 FOR_ENTITIES(itr)
1072 {
1073 Entity *e = *itr;
1074 flipRenderObjectVertical(e, flipY);
1075 }
1076 int i = 0;
1077 int flipTY = (flipY/TILE_SIZE)-1;
1078 for (i = 0; i < obsRows.size(); i++)
1079 {
1080 if (obsRows[i].ty < flipTY)
1081 obsRows[i].ty = flipTY + (flipTY - obsRows[i].ty);
1082 else
1083 obsRows[i].ty = flipTY - (obsRows[i].ty - flipTY);
1084 }
1085 for (i = 0; i < dsq->getNumElements(); i++)
1086 {
1087 Element *e = dsq->getElement(i);
1088 e->rotation.z = 180-e->rotation.z;
1089 flipRenderObjectVertical(e, flipY);
1090 }
1091 /*
1092 // DUMBASS: avatar is an entity.. it has already been flipped!
1093 if (dsq->game->avatar)
1094 {
1095 flipRenderObjectVertical(dsq->game->avatar, flipY);
1096 dsq->game->avatar->clampPosition();
1097 dsq->game->avatar->update(0.03);
1098 }
1099 */
1100 reconstructGrid();
1101 FOR_ENTITIES(i)
1102 {
1103 Entity *e = *i;
1104 e->onSceneFlipped();
1105 }
1106 reconstructGrid();
1107 if (cameraFollow)
1108 warpCameraTo(*cameraFollow);
1109 dsq->resetTimer();
1110 }
1111
setMenuDescriptionText(const std::string & text)1112 void Game::setMenuDescriptionText(const std::string &text)
1113 {
1114 menuDescription->setText(text);
1115 }
1116
1117 Game *game = 0;
1118
spawnIngredient(const std::string & ing,const Vector & pos,int times,int out)1119 Ingredient *Game::spawnIngredient(const std::string &ing, const Vector &pos, int times, int out)
1120 {
1121 std::string use = ing;
1122 Ingredient *i = 0;
1123 for (int c = 0; c < times; c++)
1124 {
1125 //HACK:
1126 if (nocasecmp(ing, "poultice")==0)
1127 use = "LeafPoultice";
1128
1129 IngredientData *d = dsq->continuity.getIngredientDataByName(use);
1130 if (d)
1131 {
1132 i = new Ingredient(pos, d);
1133 ingredients.push_back(i);
1134 if (out)
1135 {
1136 /*
1137 if (i->velocity.y > i->velocity.x)
1138 {
1139 i->velocity.x = i->velocity.y;
1140 i->velocity.y = -500;
1141 }
1142 if (i->velocity.y > 0)
1143 i->velocity.y *= -1;
1144 */
1145
1146 i->velocity.x = 0;
1147 i->velocity.y = -500;
1148 }
1149 establishEntity(i);
1150 //addRenderObject(i, LR_ENTITIES);
1151 }
1152 else
1153 {
1154 debugLog("Could not find ingredient data for [" + use + "]");
1155 }
1156 }
1157 return i;
1158 }
1159
spawnIngredientFromEntity(Entity * ent,IngredientData * data)1160 void Game::spawnIngredientFromEntity(Entity *ent, IngredientData *data)
1161 {
1162 Ingredient *i = new Ingredient(ent->position, data);
1163 ingredients.push_back(i);
1164 establishEntity(i);
1165 //addRenderObject(i, LR_ENTITIES);
1166 }
1167
Game()1168 Game::Game() : StateObject()
1169 {
1170 applyingState = false;
1171 blurEffectsCheck = 0;
1172 ripplesCheck = 0;
1173
1174 cookDelay = 0;
1175
1176 #if defined(AQUARIA_DEMO)
1177 allowedMaps.push_back("naijacave");
1178 allowedMaps.push_back("trainingcave");
1179 allowedMaps.push_back("mainarea");
1180 allowedMaps.push_back("vedhacave");
1181 allowedMaps.push_back("openwater02");
1182 allowedMaps.push_back("energytemple01");
1183 allowedMaps.push_back("energytemple02");
1184 allowedMaps.push_back("energytemple03");
1185 allowedMaps.push_back("energytemple04");
1186 allowedMaps.push_back("energytemple05");
1187 allowedMaps.push_back("energytemple06");
1188 allowedMaps.push_back("songcave");
1189 allowedMaps.push_back("songcave02");
1190 allowedMaps.push_back("title");
1191 allowedMaps.push_back("energytemplevision");
1192 #endif
1193
1194 hasPlayedLow = false;
1195
1196 invincibleOnNested = true;
1197 activation = false;
1198 invinciblity = false;
1199
1200 active = false;
1201
1202 registerState(this, "Game");
1203
1204 optionsOnly = false;
1205
1206 toFlip = -1;
1207 shuttingDownGameState = false;
1208 dsq->loops.bg = BBGE_AUDIO_NOCHANNEL;
1209 dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL;
1210
1211
1212 loadingScene = false;
1213 controlHint_mouseLeft = controlHint_mouseRight = controlHint_mouseMiddle = controlHint_mouseBody = controlHint_bg = 0;
1214 controlHint_text = 0;
1215
1216 avatar = 0;
1217 fromVel = Vector(0,-1);
1218 currentInventoryPage = 0;
1219 deathTimer = 0;
1220
1221 game = this;
1222 elementWithMenu = 0;
1223 cameraFollow = 0;
1224
1225 worldMapRender = 0;
1226
1227 for (int i = 0; i < PATH_MAX; i++)
1228 firstPathOfType[i] = 0;
1229
1230 loadEntityTypeList();
1231
1232 lastCollideMaskIndex = -1;
1233 worldPaused = false;
1234
1235 cookingScript = 0;
1236
1237 }
1238
~Game()1239 Game::~Game()
1240 {
1241 tileCache.clean();
1242 game = 0;
1243 }
1244 /*
1245 void Game::doChoiceMenu(Vector position, std::vector<std::string> choices)
1246 {
1247 dsq->gui.openChoiceMenu(position);
1248 for (int i = 0; i < choices.size(); i++)
1249 {
1250 dsq->gui.choiceMenu.addEntry(choices[i]);
1251 }
1252 selectedChoice = "";
1253 while (selectedChoice.empty())
1254 {
1255 dsq->delay(10);
1256 }
1257 dsq->gui.closeChoiceMenu();
1258 }
1259 */
1260
1261 /*
1262 void Game::onAssignMenuScreenItemToSlot0()
1263 {
1264 if (!dsq->continuity.hudVisible) return;
1265 if (!selectedMenuScreenItem) return;
1266 dsq->continuity.setItemSlot(0, selectedMenuScreenItem->getItemIndex());
1267 }
1268
1269 void Game::onAssignMenuScreenItemToSlot1()
1270 {
1271 if (!dsq->continuity.hudVisible) return;
1272 if (!selectedMenuScreenItem) return;
1273 dsq->continuity.setItemSlot(1, selectedMenuScreenItem->getItemIndex());
1274 }
1275
1276 void Game::onAssignMenuScreenItemToSlot2()
1277 {
1278 if (!dsq->continuity.hudVisible) return;
1279 if (!selectedMenuScreenItem) return;
1280 dsq->continuity.setItemSlot(2, selectedMenuScreenItem->getItemIndex());
1281 }
1282
1283 void Game::onAssignMenuScreenItemToSlot3()
1284 {
1285 if (!dsq->continuity.hudVisible) return;
1286 if (!selectedMenuScreenItem) return;
1287 dsq->continuity.setItemSlot(3, selectedMenuScreenItem->getItemIndex());
1288 }
1289 */
1290
1291 Quad *menu_blackout = 0;
1292
showInGameMenu(bool ignoreInput,bool optionsOnly,MenuPage menuPage)1293 void Game::showInGameMenu(bool ignoreInput, bool optionsOnly, MenuPage menuPage)
1294 {
1295 if (avatar && core->getNestedMains()==1 && !avatar->isSinging() && (ignoreInput || avatar->isInputEnabled()))
1296 {
1297 //dsq->toggleInputGrabPlat(false);
1298
1299 dsq->game->clearControlHint();
1300
1301 selectedTreasureFlag = -1;
1302 this->optionsOnly = optionsOnly;
1303
1304 core->sound->playSfx("Menu-Open");
1305 dropIngrNames.clear();
1306
1307 if (avatar->isEntityDead()) return;
1308
1309 if (dsq->game->autoMap && dsq->game->autoMap->isOn())
1310 dsq->game->autoMap->toggle(false);
1311
1312 toggleOptionsMenu(false);
1313 dsq->overlay->alpha.interpolateTo(0, 0.1);
1314 float t = 0.3;
1315
1316
1317 if (!optionsOnly)
1318 {
1319 togglePause(true);
1320 }
1321
1322 if (optionsOnly)
1323 {
1324 menu_blackout = new Quad;
1325 menu_blackout->color = 0;
1326 menu_blackout->autoWidth = AUTO_VIRTUALWIDTH;
1327 menu_blackout->autoHeight = AUTO_VIRTUALHEIGHT;
1328 menu_blackout->followCamera = 1;
1329 menu_blackout->position = Vector(400,300);
1330 menu_blackout->alphaMod = 0.75;
1331 menu_blackout->alpha = 0;
1332 menu_blackout->alpha.interpolateTo(1, 0.5);
1333 addRenderObject(menu_blackout, LR_AFTER_EFFECTS);
1334
1335 menuBg2->alpha = 0;
1336 }
1337 else
1338 {
1339 menuBg2->alpha = 0;
1340 menuBg2->alpha.interpolateTo(1, t*0.5f);
1341 }
1342
1343 if (dsq->continuity.hasFormUpgrade(FORMUPGRADE_ENERGY2))
1344 energyIdol->alphaMod = 1;
1345 else
1346 energyIdol->alphaMod = 0;
1347
1348 if (dsq->continuity.getFlag(FLAG_LI) >= 100)
1349 liCrystal->alphaMod = 1;
1350 else
1351 liCrystal->alphaMod = 0;
1352
1353 int i = 0;
1354
1355
1356 for (i = 0; i < songSlots.size(); i++)
1357 {
1358 if (dsq->continuity.hasSong(dsq->continuity.getSongTypeBySlot(i)))
1359 songSlots[i]->alpha.interpolateTo(1, t);
1360 else
1361 songSlots[i]->alpha = 0;
1362 }
1363
1364
1365
1366 /*
1367 std::ostringstream os;
1368 os << "Exp: " << dsq->continuity.exp;
1369 menuEXP->setText(os.str());
1370 menuEXP->alpha.interpolateTo(1, 0.5);
1371
1372 std::ostringstream os2;
1373 os2 << "Money: " << dsq->continuity.money;
1374 menuMoney->setText(os2.str());
1375 menuMoney->alpha.interpolateTo(1, 0.5);
1376 */
1377
1378 menuDescription->setText("");
1379
1380 menuDescription->alpha.interpolateTo(1, t);
1381
1382 menuBg->scale = menuBgScale*0.5f;
1383 menuBg->scale.interpolateTo(menuBgScale, t);
1384 menuBg->alpha.interpolateTo(1, t*0.5f);
1385 menuBg->setHidden(false);
1386
1387 // FIXME: This gets a little verbose because of all the
1388 // individual non-child objects. Is there a reason they
1389 // can't all be children of menuBg? --achurch
1390 opt_save->setHidden(false);
1391 opt_cancel->setHidden(false);
1392 options->setHidden(false);
1393 keyConfigButton->setHidden(false);
1394 cook->setHidden(false);
1395 foodSort->setHidden(false);
1396 recipes->setHidden(false);
1397 use->setHidden(false);
1398 prevFood->setHidden(false);
1399 nextFood->setHidden(false);
1400 prevTreasure->setHidden(false);
1401 nextTreasure->setHidden(false);
1402 circlePageNum->setHidden(false);
1403 previewRecipe->setHidden(false);
1404 showRecipe->setHidden(false);
1405 recipeMenu.scroll->setHidden(false);
1406 recipeMenu.scrollEnd->setHidden(false);
1407 recipeMenu.header->setHidden(false);
1408 recipeMenu.page->setHidden(false);
1409 recipeMenu.prevPage->setHidden(false);
1410 recipeMenu.nextPage->setHidden(false);
1411 menuDescription->setHidden(false);
1412 eAre->setHidden(false);
1413 eYes->setHidden(false);
1414 eNo->setHidden(false);
1415 menuIconGlow->setHidden(false);
1416 for (int i = 0; i < menu.size(); i++)
1417 menu[i]->setHidden(false);
1418 for (int i = 0; i < treasureSlots.size(); i++)
1419 treasureSlots[i]->setHidden(false);
1420 treasureDescription->setHidden(false);
1421 for (int i = 0; i < foodSlots.size(); i++)
1422 foodSlots[i]->setHidden(false);
1423
1424
1425 if (dsq->game->miniMapRender)
1426 {
1427 dsq->game->miniMapRender->slide(1);
1428 }
1429
1430 toggleMainMenu(false);
1431
1432 dsq->main(t);
1433
1434 dsq->screenTransition->capture();
1435
1436 //toggleMiniMapRender(0);
1437
1438 MenuPage useMenuPage = MENUPAGE_NONE;
1439
1440 if (!optionsOnly)
1441 {
1442 if (menuPage != MENUPAGE_NONE)
1443 {
1444 useMenuPage = menuPage;
1445 }
1446 else if (dsq->continuity.lastMenuPage != MENUPAGE_NONE)
1447 {
1448 //errorLog("setting last menu page");
1449 useMenuPage = dsq->continuity.lastMenuPage;
1450 }
1451 }
1452
1453
1454 switch(useMenuPage)
1455 {
1456 case MENUPAGE_FOOD:
1457 toggleFoodMenu(true);
1458 ((AquariaMenuItem*)menu[6])->setFocus(true);
1459 break;
1460 case MENUPAGE_TREASURES:
1461 toggleTreasureMenu(true);
1462 break;
1463 case MENUPAGE_PETS:
1464 togglePetMenu(true);
1465 break;
1466 case MENUPAGE_SONGS:
1467 default:
1468 {
1469 if (optionsOnly)
1470 {
1471 toggleOptionsMenu(true);
1472 }
1473 else
1474 {
1475 float t = 0.1;
1476
1477 toggleMainMenu(true);
1478
1479 songBubbles->alpha.interpolateTo(1, t);
1480 if (menuSongs)
1481 {
1482 menuSongs->alpha.interpolateTo(1, t);
1483 }
1484 for (i = 0; i < menu.size(); i++)
1485 {
1486 menu[i]->scale = Vector(0,0);
1487 menu[i]->alpha = 0;
1488 }
1489 ((AquariaMenuItem*)menu[5])->setFocus(true);
1490 }
1491 }
1492 }
1493
1494
1495 if (!optionsOnly)
1496 {
1497 for (i = 0; i < menu.size(); i++)
1498 {
1499 menu[i]->scale.interpolateTo(Vector(1, 1), 0.15);
1500
1501 menu[i]->alpha.interpolateTo(1, 0.15);
1502 }
1503
1504 menuIconGlow->alpha.interpolateTo(1, 0.5);
1505 }
1506
1507 menuOpenTimer = 0;
1508
1509 inGameMenu = true;
1510
1511
1512
1513 dsq->routeShoulder = false;
1514
1515
1516 dsq->screenTransition->transition(MENUPAGETRANSTIME);
1517
1518
1519
1520 if (optionsOnly)
1521 {
1522 dsq->main(-1);
1523 }
1524 }
1525 }
1526
pickupIngredientEffects(IngredientData * data)1527 void Game::pickupIngredientEffects(IngredientData *data)
1528 {
1529 Quad *q = new Quad("gfx/ingredients/" + data->gfx, Vector(800-20 + core->getVirtualOffX(), (570-2*(100*miniMapRender->scale.y))+ingOffY));
1530 q->scale = Vector(0.8, 0.8);
1531 q->followCamera = 1;
1532 q->alpha.ensureData();
1533 q->alpha.data->path.addPathNode(0, 0);
1534 q->alpha.data->path.addPathNode(1.0, 0.1);
1535 q->alpha.data->path.addPathNode(0, 1.0);
1536 q->alpha.startPath(2);
1537 q->setLife(1);
1538 q->setDecayRate(0.5);
1539 addRenderObject(q, LR_HELP);
1540 ingOffY -= 40;
1541 ingOffYTimer = 2;
1542 }
1543
hideInGameMenu(bool effects,bool cancel)1544 void Game::hideInGameMenu(bool effects, bool cancel)
1545 {
1546 if (isCooking) return;
1547 if (FoodSlot::foodSlotIndex != -1) return;
1548 if (effects && !this->isInGameMenu()) return;
1549
1550 if (avatar)
1551 {
1552 if (resBox)
1553 resBox->close();
1554
1555 //dsq->toggleInputGrabPlat(true);
1556
1557 if (effects)
1558 core->sound->playSfx("Menu-Close");
1559
1560 hideInGameMenuExitCheck(false);
1561 playingSongInMenu = -1;
1562
1563
1564 float t = 0.3;
1565
1566 if (!effects)
1567 t = 0;
1568 //if (avatar->isEntityDead()) return;
1569
1570 int i = 0;
1571
1572 for (i = 0; i < foodHolders.size(); i++)
1573 {
1574 foodHolders[i]->dropFood();
1575 }
1576
1577 dsq->continuity.lastMenuPage = currentMenuPage;
1578 if(cancel && (optionsMenu || keyConfigMenu))
1579 onOptionsCancel();
1580 else
1581 toggleOptionsMenu(false);
1582
1583 if (!optionsOnly)
1584 {
1585 toggleFoodMenu(false);
1586 toggleTreasureMenu(false);
1587 togglePetMenu(false);
1588 toggleMainMenu(false);
1589 toggleKeyConfigMenu(false);
1590 }
1591
1592 menuIconGlow->alpha = 0;
1593
1594 for (i = 0; i < menu.size(); i++)
1595 {
1596 menu[i]->alpha = 0;
1597 //menu[i]->alpha.interpolateTo(0, t*0.5f);
1598 //menu[i]->scale.interpolateTo(Vector(0, 0), t);
1599 }
1600 for (i = 0; i < spellIcons.size(); i++)
1601 spellIcons[i]->alpha.interpolateTo(0, t);
1602 for (i = 0; i < songSlots.size(); i++)
1603 songSlots[i]->alpha.interpolateTo(0, t);
1604 songBubbles->alpha.interpolateTo(0, t);
1605
1606 /*
1607 menuEXP->alpha.interpolateTo(0, t);
1608 menuMoney->alpha.interpolateTo(0, t);
1609 */
1610 if (dsq->game->miniMapRender)
1611 dsq->game->miniMapRender->slide(0);
1612
1613 menuDescription->alpha.interpolateTo(0, t);
1614 menuBg->alpha.interpolateTo(0, t);
1615 menuBg->scale.interpolateTo(menuBg->scale*0.5f, t);
1616 menuBg2->alpha.interpolateTo(0, t);
1617
1618
1619
1620 if (menuSongs)
1621 menuSongs->alpha.interpolateTo(0, t);
1622
1623 if (menu_blackout)
1624 {
1625 menu_blackout->alpha.interpolateTo(0, t);
1626 }
1627
1628 if (showRecipe)
1629 {
1630 showRecipe->alpha.interpolateTo(0, t);
1631 }
1632
1633 if (effects)
1634 core->main(t);
1635
1636 if (menu_blackout)
1637 {
1638 menu_blackout->safeKill();
1639 menu_blackout = 0;
1640 }
1641 if (effects)
1642 togglePause(false);
1643 inGameMenu = false;
1644 //toggleMiniMapRender(1);
1645
1646 for (int i = 0; i < songTips.size(); i++)
1647 songTips[i]->alpha = 0;
1648
1649
1650
1651
1652 for (int i = 0; i < dropIngrNames.size(); i++)
1653 {
1654 dsq->game->spawnIngredient(dropIngrNames[i], avatar->position + Vector(0,-96), 1, 1);
1655 }
1656 dropIngrNames.clear();
1657
1658 if (effects)
1659 dsq->quitNestedMain();
1660
1661 dsq->routeShoulder = true;
1662 }
1663
1664 menuBg->setHidden(true);
1665 opt_save->setHidden(true);
1666 opt_cancel->setHidden(true);
1667 options->setHidden(true);
1668 keyConfigButton->setHidden(true);
1669 cook->setHidden(true);
1670 foodSort->setHidden(true);
1671 recipes->setHidden(true);
1672 use->setHidden(true);
1673 prevFood->setHidden(true);
1674 nextFood->setHidden(true);
1675 prevTreasure->setHidden(true);
1676 nextTreasure->setHidden(true);
1677 circlePageNum->setHidden(true);
1678 previewRecipe->setHidden(true);
1679 showRecipe->setHidden(true);
1680 recipeMenu.scroll->setHidden(true);
1681 recipeMenu.scrollEnd->setHidden(true);
1682 recipeMenu.header->setHidden(true);
1683 recipeMenu.page->setHidden(true);
1684 recipeMenu.prevPage->setHidden(true);
1685 recipeMenu.nextPage->setHidden(true);
1686 menuDescription->setHidden(true);
1687 eAre->setHidden(true);
1688 eYes->setHidden(true);
1689 eNo->setHidden(true);
1690 menuIconGlow->setHidden(true);
1691 for (int i = 0; i < menu.size(); i++)
1692 menu[i]->setHidden(true);
1693 for (int i = 0; i < treasureSlots.size(); i++)
1694 treasureSlots[i]->setHidden(true);
1695 treasureDescription->setHidden(true);
1696 for (int i = 0; i < foodSlots.size(); i++)
1697 foodSlots[i]->setHidden(true);
1698 }
1699
onLeftMouseButton()1700 void Game::onLeftMouseButton()
1701 {
1702 // hud button
1703 /*
1704 if (avatar && !avatar->isCharging())
1705 {
1706
1707 if ((core->mouse.position - Vector(20, 20)).getSquaredLength2D() < sqr(40))
1708 {
1709 if (paused)
1710 hideInGameMenu();
1711 else
1712 showInGameMenu();
1713 }
1714 }
1715 */
1716 }
1717
1718 /*
1719 void Game::onActivate()
1720 {
1721 if (!dsq->gui.isInteractionSelectorOpen() && avatar->isInputEnabled())
1722 {
1723 Element * e = dsq->getElementAtVector(dsq->cursor->position);
1724 if (e)
1725 {
1726 // open a pop-up menu
1727 // how?
1728 // gui system
1729 // embed menu control in all elements?
1730 // if in all elements -> stupid, because you can only have on menu at once
1731 elementWithMenu = e;
1732 dsq->gui.openInteractionSelectorForElement(e);
1733 }
1734 }
1735
1736 if (dsq->gui.isInteractionSelectorOpen())
1737 {
1738 if (dsq->gui.menu.getSelectedEntry() > -1)
1739 {
1740 Interaction::Type type = elementWithMenu->interactions[dsq->gui.menu.getSelectedEntry()].getType();
1741 dsq->gui.closeInteractionSelector();
1742 // will crash sometime
1743 elementWithMenu->interact(type, avatar);
1744 elementWithMenu = 0;
1745
1746
1747 avatar->enableInput();
1748 //dsq->gui.menu.clearEntries();
1749 }
1750 }
1751 else if (dsq->gui.isChoiceMenuOpen())
1752 {
1753 if (dsq->gui.choiceMenu.getSelectedEntry() > -1)
1754 {
1755 selectedChoice = dsq->gui.choiceMenu.getSelectedEntryName();
1756 dsq->gui.closeChoiceMenu();
1757 if (core->getNestedMains() > 1)
1758 {
1759 core->quitNestedMain();
1760 }
1761 }
1762 }
1763 else if(core->getNestedMains())
1764 {
1765 core->quitNestedMain();
1766 }
1767 }
1768 */
1769
spawnManaBall(Vector pos,float a)1770 void Game::spawnManaBall(Vector pos, float a)
1771 {
1772 ManaBall *m = new ManaBall(pos, a);
1773 addRenderObject(m, LR_PARTICLES);
1774 }
1775
refreshItemSlotIcons()1776 void Game::refreshItemSlotIcons()
1777 {
1778 /*
1779 for (int i = 0; i < itemSlotIcons.size(); i++)
1780 {
1781 if (dsq->continuity.itemSlots[i] != -1)
1782 {
1783 itemSlotIcons[i]->setTexture(dsq->getItemTexture(dsq->continuity.itemSlots[i]));
1784 int n = dsq->continuity.getNumberOf(dsq->continuity.itemSlots[i]);
1785 if (n > 0)
1786 itemSlotIcons[i]->alpha = 1;
1787 else
1788 itemSlotIcons[i]->alpha = 0;
1789 }
1790 else
1791 itemSlotIcons[i]->alpha = 0;
1792 itemSlotIcons[i]->setWidthHeight(32, 32);
1793
1794
1795 }
1796 */
1797 /*
1798 if (n > 0)
1799 itemSlotIcons[i]->alpha.interpolateTo(1,0.2);
1800 else
1801 itemSlotIcons[i]->alpha.interpolateTo(0,0.2);
1802 */
1803 }
1804
clearPointers()1805 void Game::clearPointers()
1806 {
1807 bg = 0;
1808 bg2 = 0;
1809 avatar = 0;
1810 }
1811
warpPrep()1812 void Game::warpPrep()
1813 {
1814 avatar->onWarp();
1815 fromVel = avatar->vel;
1816 fromVel.setLength2D(10);
1817 fromPosition = avatar->position;
1818 }
1819
warpToSceneNode(std::string scene,std::string node)1820 void Game::warpToSceneNode(std::string scene, std::string node)
1821 {
1822 warpPrep();
1823
1824 sceneToLoad = scene;
1825 toNode = node;
1826 stringToLower(sceneToLoad);
1827 stringToLower(toNode);
1828
1829 if (avatar->isfh())
1830 toFlip = 1;
1831
1832
1833 core->enqueueJumpState("Game");
1834 }
1835
warpToSceneFromNode(Path * p)1836 void Game::warpToSceneFromNode( Path *p)
1837 {
1838 warpPrep();
1839
1840 sceneToLoad = p->warpMap;
1841
1842 toNode = "";
1843 if (!p->warpNode.empty())
1844 {
1845 toNode = p->warpNode;
1846 toFlip = p->toFlip;
1847 stringToLower(toNode);
1848 }
1849 else
1850 {
1851 fromScene = sceneName;
1852 fromWarpType = p->warpType;
1853 }
1854
1855 stringToLower(fromScene);
1856 stringToLower(sceneToLoad);
1857
1858 core->enqueueJumpState("Game");
1859 }
1860
transitionToScene(std::string scene)1861 void Game::transitionToScene(std::string scene)
1862 {
1863 if (avatar)
1864 {
1865 avatar->onWarp();
1866 }
1867 sceneToLoad = scene;
1868 stringToLower(sceneToLoad);
1869
1870 core->enqueueJumpState("Game", false);
1871 }
1872
getElementTemplateByIdx(int idx)1873 ElementTemplate *Game::getElementTemplateByIdx(int idx)
1874 {
1875 for (int i = 0; i < elementTemplates.size(); i++)
1876 {
1877 if (elementTemplates[i].idx == idx)
1878 {
1879 return &elementTemplates[i];
1880 }
1881 }
1882 return 0;
1883 }
1884
createElement(int idx,Vector position,int bgLayer,RenderObject * copy,ElementTemplate * et)1885 Element* Game::createElement(int idx, Vector position, int bgLayer, RenderObject *copy, ElementTemplate *et)
1886 {
1887 if (idx == -1) return 0;
1888
1889 if (!et)
1890 et = this->getElementTemplateByIdx(idx);
1891
1892 Element *element = new Element();
1893 if (et)
1894 {
1895 element->setTexture(et->gfx);
1896 element->alpha = et->alpha;
1897 }
1898
1899 element->position = position;
1900 element->position.z = -0.05;
1901 element->templateIdx = idx;
1902
1903 element->bgLayer = bgLayer;
1904
1905 if (et)
1906 {
1907 if (et->w != -1 && et->h != -1)
1908 element->setWidthHeight(et->w, et->h);
1909 }
1910 if (et)
1911 {
1912 if (et->tu1 != 0 || et->tu2 != 0 || et->tv1 != 0 || et->tv2 != 0)
1913 {
1914 element->upperLeftTextureCoordinates = Vector(et->tu1, et->tv1);
1915 element->lowerRightTextureCoordinates = Vector(et->tu2, et->tv2);
1916 }
1917 }
1918 if (copy)
1919 {
1920 element->scale = copy->scale;
1921 if (copy->isfh())
1922 element->flipHorizontal();
1923 if (copy->isfv())
1924 element->flipVertical();
1925 element->rotation = copy->rotation;
1926 Quad *q = dynamic_cast<Quad*>(copy);
1927 if (q)
1928 {
1929 element->repeatTextureToFill(q->isRepeatingTextureToFill());
1930 }
1931 }
1932 addRenderObject(element, LR_ELEMENTS1+bgLayer);
1933 dsq->addElement(element);
1934 //element->updateCullVariables();
1935
1936 return element;
1937 }
1938
addObsRow(int tx,int ty,int len)1939 void Game::addObsRow(int tx, int ty, int len)
1940 {
1941 ObsRow obsRow(tx, ty, len);
1942 obsRows.push_back(obsRow);
1943 }
1944
clearObsRows()1945 void Game::clearObsRows()
1946 {
1947 obsRows.clear();
1948 }
1949
fillGridFromQuad(Quad * q,ObsType obsType,bool trim)1950 void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
1951 {
1952 #ifdef BBGE_BUILD_OPENGL
1953 if (q->texture)
1954 {
1955 std::vector<TileVector> obs;
1956 TileVector tpos(q->position);
1957 int widthscale = q->getWidth()*q->scale.x;
1958 int heightscale = q->getHeight()*q->scale.y;
1959 int w2 = widthscale/2;
1960 int h2 = heightscale/2;
1961 w2/=TILE_SIZE;
1962 h2/=TILE_SIZE;
1963 tpos.x -= w2;
1964 tpos.y -= h2;
1965
1966 int w = 0, h = 0;
1967 unsigned int size = 0;
1968 unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
1969 if (!data)
1970 {
1971 debugLog("Failed to get buffer in Game::fillGridFromQuad()");
1972 return;
1973 }
1974
1975 int szx = TILE_SIZE/q->scale.x;
1976 int szy = TILE_SIZE/q->scale.y;
1977 if (szx < 1) szx = 1;
1978 if (szy < 1) szy = 1;
1979
1980 for (int tx = 0; tx < widthscale; tx+=TILE_SIZE)
1981 {
1982 for (int ty = 0; ty < heightscale; ty+=TILE_SIZE)
1983 {
1984 int num = 0;
1985 for (int x = 0; x < szx; x++)
1986 {
1987 for (int y = 0; y < szy; y++)
1988 {
1989 // starting position =
1990 // tx / scale.x
1991 unsigned int px = int(tx/q->scale.x) + x;
1992 unsigned int py = int(ty/q->scale.y) + y;
1993 if (px < unsigned(w) && py < unsigned(h))
1994 {
1995 unsigned int p = (py*unsigned(w)*4) + (px*4) + 3; // position of alpha component
1996 if (p < size && data[p] >= 254)
1997 {
1998 num ++;
1999 }
2000 else
2001 {
2002 break;
2003 }
2004 }
2005 }
2006 }
2007
2008 if (num >= int((szx*szy)*0.8f))
2009 //if (num >= int((szx*szy)))
2010 {
2011 // add tile
2012 //dsq->game->setGrid(TileVector(int(tx/TILE_SIZE)+tpos.x, int(ty/TILE_SIZE)+tpos.y), 1);
2013 obs.push_back(TileVector(int(tx/TILE_SIZE), int(ty/TILE_SIZE)));
2014 }
2015 }
2016 }
2017
2018 free(data);
2019
2020 if (trim)
2021 {
2022 std::vector<TileVector> obsCopy;
2023 obsCopy.swap(obs);
2024 // obs now empty
2025
2026 int sides = 0;
2027 for (int i = 0; i < obsCopy.size(); i++)
2028 {
2029 sides = 0;
2030 for (int j = 0; j < obsCopy.size(); j++)
2031 {
2032 if (i != j)
2033 {
2034 if (
2035 (obsCopy[j].x == obsCopy[i].x-1 && obsCopy[j].y == obsCopy[i].y)
2036 || (obsCopy[j].x == obsCopy[i].x+1 && obsCopy[j].y == obsCopy[i].y)
2037 || (obsCopy[j].y == obsCopy[i].y-1 && obsCopy[j].x == obsCopy[i].x)
2038 || (obsCopy[j].y == obsCopy[i].y+1 && obsCopy[j].x == obsCopy[i].x)
2039 )
2040 {
2041 sides++;
2042 }
2043 if (sides>=4)
2044 {
2045 obs.push_back(obsCopy[i]);
2046 break;
2047 }
2048 }
2049 }
2050 }
2051 }
2052
2053
2054 glPushMatrix();
2055
2056 for (int i = 0; i < obs.size(); i++)
2057 {
2058 glLoadIdentity();
2059
2060 glRotatef(q->rotation.z, 0, 0, 1);
2061 if (q->isfh())
2062 {
2063 glRotatef(180, 0, 1, 0);
2064 }
2065
2066 //glTranslatef((obs[i].x-w2)*TILE_SIZE+TILE_SIZE/2, (obs[i].y-h2)*TILE_SIZE + TILE_SIZE/2, 0);
2067 glTranslatef((obs[i].x-w2), (obs[i].y-h2), 0);
2068
2069 float m[16];
2070 glGetFloatv(GL_MODELVIEW_MATRIX, m);
2071 float x = m[12];
2072 float y = m[13];
2073
2074 //dsq->game->setGrid(TileVector(tpos.x+(w2*TILE_SIZE)+(x/TILE_SIZE), tpos.y+(h2*TILE_SIZE)+(y/TILE_SIZE)), obsType);
2075 TileVector tvec(tpos.x+w2+x, tpos.y+h2+y);
2076 if (!dsq->game->isObstructed(tvec))
2077 dsq->game->addGrid(tvec, obsType);
2078
2079 }
2080 glPopMatrix();
2081 }
2082 #endif
2083 }
2084
getNoteName(int n,const std::string & pre)2085 std::string Game::getNoteName(int n, const std::string &pre)
2086 {
2087 std::ostringstream os;
2088 os << pre << "Note" << n;
2089
2090 if (n == 6 && bNatural)
2091 {
2092 os << "b";
2093 }
2094 //debugLog(os.str());
2095 return os.str();
2096 }
2097
clearDynamicGrid(unsigned char maskbyte)2098 void Game::clearDynamicGrid(unsigned char maskbyte /* = OT_MASK_BLACK */)
2099 {
2100 // just to be sure in case the grid/type sizes change,
2101 // otherwise there is a chance to write a few bytes over the end of the buffer -- FG
2102 compile_assert(sizeof(grid) % sizeof(uint32) == 0);
2103
2104 unsigned char *gridstart = &grid[0][0];
2105 uint32 *gridend = (uint32*)(gridstart + sizeof(grid));
2106 uint32 *gridptr = (uint32*)gridstart;
2107 // mask out specific bytes
2108 // use full uint32 rounds instead of single-bytes to speed things up.
2109 const uint32 mask = maskbyte | (maskbyte << 8) | (maskbyte << 16) | (maskbyte << 24);
2110 do
2111 {
2112 *gridptr &= mask;
2113 ++gridptr;
2114 }
2115 while(gridptr < gridend);
2116 }
2117
reconstructEntityGrid()2118 void Game::reconstructEntityGrid()
2119 {
2120 clearDynamicGrid(~OT_INVISIBLEENT);
2121
2122 FOR_ENTITIES(i)
2123 {
2124 Entity *e = *i;
2125 e->fillGrid();
2126 }
2127 }
2128
reconstructGrid(bool force)2129 void Game::reconstructGrid(bool force)
2130 {
2131 if (!force && isSceneEditorActive()) return;
2132
2133 clearGrid();
2134 int i = 0;
2135 for (i = 0; i < dsq->getNumElements(); i++)
2136 {
2137 Element *e = dsq->getElement(i);
2138 e->fillGrid();
2139 }
2140
2141 ObsRow *o;
2142 for (i = 0; i < obsRows.size(); i++)
2143 {
2144 o = &obsRows[i];
2145 for (int tx = 0; tx < o->len; tx++)
2146 {
2147 setGrid(TileVector(o->tx + tx, o->ty), OT_BLACK);
2148 }
2149 }
2150
2151 FOR_ENTITIES(i)
2152 {
2153 Entity *e = *i;
2154 e->fillGrid();
2155 }
2156
2157 trimGrid();
2158 }
2159
trimGrid()2160 void Game::trimGrid()
2161 {
2162 // Prevent the left- and rightmost column of black tiles
2163 // from beeing drawn. (The maps were designed with this mind...)
2164 for (int x = 0; x < MAX_GRID; x++)
2165 {
2166 const unsigned char *curCol = grid[x]; // safe
2167 const unsigned char *leftCol = dsq->game->getGridColumn(x-1); // unsafe
2168 const unsigned char *rightCol = dsq->game->getGridColumn(x+1); // unsafe
2169 for (int y = 0; y < MAX_GRID; y++)
2170 {
2171 if (curCol[y] & OT_MASK_BLACK)
2172 {
2173 if (!(leftCol[y] & OT_MASK_BLACK) || !(rightCol[y] & OT_MASK_BLACK))
2174 setGrid(TileVector(x, y), OT_BLACKINVIS);
2175 }
2176 }
2177 }
2178 }
2179
dilateGrid(unsigned int radius,ObsType test,ObsType set,ObsType allowOverwrite)2180 void Game::dilateGrid(unsigned int radius, ObsType test, ObsType set, ObsType allowOverwrite)
2181 {
2182 if(!radius)
2183 return;
2184 const int lim = MAX_GRID - radius;
2185 const unsigned int denyOverwrite = ~allowOverwrite;
2186 // Box dilation is separable, so we do a two-pass by axis
2187 int dilate = 0;
2188
2189 // dilate rows
2190 for (int y = 0; y < MAX_GRID; ++y)
2191 {
2192 for (int x = radius; x < lim; ++x)
2193 {
2194 if (grid[x][y] & test)
2195 {
2196 dilate = 2 * radius;
2197 goto doDilate1;
2198 }
2199 if(dilate)
2200 {
2201 --dilate;
2202 doDilate1:
2203 if((grid[x - radius][y] & denyOverwrite) == OT_EMPTY)
2204 grid[x - radius][y] |= set;
2205 }
2206 }
2207 assert(lim + dilate < MAX_GRID);
2208 for(int x = 0; x < dilate; ++x)
2209 if(!(grid[x][y - radius] & test))
2210 grid[x][y - radius] |= set;
2211 }
2212
2213 // dilate colums
2214 dilate = 0;
2215 for (int x = 0; x < MAX_GRID; ++x)
2216 {
2217 unsigned char * const curCol = grid[x];
2218 for (int y = radius; y < lim; ++y)
2219 {
2220 if (curCol[y] & test)
2221 {
2222 dilate = 2 * radius;
2223 goto doDilate2;
2224 }
2225 if(dilate)
2226 {
2227 --dilate;
2228 doDilate2:
2229 if((curCol[y - radius] & denyOverwrite) == OT_EMPTY)
2230 curCol[y - radius] |= set;
2231 }
2232 }
2233 assert(lim + dilate < MAX_GRID);
2234 for(int y = 0; y < dilate; ++y)
2235 if(!(curCol[y - radius] & test))
2236 curCol[y - radius] |= set;
2237 }
2238 }
2239
getCoverage(Vector pos,int sampleArea)2240 float Game::getCoverage(Vector pos, int sampleArea)
2241 {
2242 TileVector t(pos);
2243 int total = 0, covered = 0;
2244 for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++)
2245 {
2246 for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++)
2247 {
2248 if (x == t.x && y == t.y) continue;
2249 TileVector ct(x,y);
2250 Vector vt = ct.worldVector();
2251 if (isObstructed(ct))
2252 {
2253 covered++;
2254 }
2255 total++;
2256 }
2257 }
2258 return float(covered)/float(total);
2259 }
2260
getPercObsInArea(Vector pos,int sampleArea,int obs)2261 float Game::getPercObsInArea(Vector pos, int sampleArea, int obs)
2262 {
2263 int sz = sampleArea * sampleArea;
2264 int c = 0;
2265 TileVector t(pos);
2266
2267 for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++)
2268 {
2269 for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++)
2270 {
2271 if (isObstructed(TileVector(x, y), obs))
2272 {
2273 c++;
2274 }
2275 }
2276 }
2277 return float(c)/float(sz);
2278 }
2279
getWallNormal(Vector pos,int sampleArea,float * dist,int obs)2280 Vector Game::getWallNormal(Vector pos, int sampleArea, float *dist, int obs)
2281 {
2282 TileVector t(pos);
2283 //Vector p = t.worldVector();
2284 Vector avg;
2285 int c = 0;
2286 //float maxLen = -1;
2287 std::vector<Vector> vs;
2288 if (dist != NULL)
2289 *dist = -1;
2290 for (int x = t.x-sampleArea; x <= t.x+sampleArea; x++)
2291 {
2292 for (int y = t.y-sampleArea; y <= t.y+sampleArea; y++)
2293 {
2294 if (x == t.x && y == t.y) continue;
2295 TileVector ct(x,y);
2296 Vector vt = ct.worldVector();
2297 if (isObstructed(ct, obs))
2298 {
2299 /*
2300 int xDiff = abs(t.x - x);
2301 int yDiff = abs(t.y - y);
2302 float xv = float(sampleArea-xDiff)/float(sampleArea);
2303 if (x < t.x)
2304 xv = -xv;
2305 float yv = float(sampleArea-yDiff)/float(sampleArea);
2306 if (y < t.y)
2307 yv = -yv;
2308 Vector v(-xv, -yv);
2309 */
2310 /*
2311 int xDiff = t.x-x;
2312 int yDiff = t.y-y;
2313 */
2314
2315 int xDiff = pos.x-vt.x;
2316 int yDiff = pos.y-vt.y;
2317 /*
2318 float xEffect = (sampleArea*TILE_SIZE - abs(xDiff))*1.0f;
2319 float yEffect = (sampleArea*TILE_SIZE - abs(yDiff))*1.0f;
2320 */
2321 //Vector v(xDiff*xEffect, yDiff*yEffect);
2322 Vector v(xDiff, yDiff);
2323 vs.push_back (v);
2324
2325 if (dist!=NULL)
2326 {
2327 float d = (vt-pos).getLength2D();
2328 if (*dist == -1 || d < *dist)
2329 {
2330 *dist = d;
2331 }
2332 }
2333 /*
2334 float len = v.getLength2D();
2335 if (len > maxLen || maxLen == -1)
2336 maxLen = len;
2337 */
2338 //Vector v(xDiff, yDiff);
2339 //avg += v;
2340 //c++;
2341 }
2342 }
2343 }
2344 int sz = (TILE_SIZE*(sampleArea-1));
2345 for (int i = 0; i < vs.size(); i++)
2346 {
2347 float len = vs[i].getLength2D();
2348 if (len < sz)
2349 {
2350 vs[i].setLength2D(sz - len);
2351 c++;
2352 avg += vs[i];
2353 }
2354 }
2355 if (c)
2356 {
2357 avg /= c;
2358 if (avg.x != 0 || avg.y != 0)
2359 {
2360 avg.normalize2D();
2361 avg.z = 0;
2362 }
2363 }
2364 else
2365 {
2366 avg.x = avg.y = 0;
2367 }
2368
2369 /*
2370 avg.x = -avg.x;
2371 avg.y = -avg.y;
2372 */
2373 return avg;
2374 }
2375
getEntityAtCursor()2376 Entity *Game::getEntityAtCursor()
2377 {
2378 int minDist = -1;
2379 Entity *selected = 0;
2380 FOR_ENTITIES(i)
2381 {
2382 Entity *e = *i;
2383 int dist = (e->position - dsq->getGameCursorPosition()).getSquaredLength2D();
2384 if (dist < sqr(64) && (minDist == -1 || dist < minDist))
2385 {
2386 selected = e;
2387 dist = minDist;
2388 }
2389 }
2390 return selected;
2391 }
2392
2393 // WARNING: will remove from save file, if present!
removeEntityAtCursor()2394 bool Game::removeEntityAtCursor()
2395 {
2396 Entity *selected = getEntityAtCursor();
2397 if (selected)
2398 {
2399 return removeEntity(selected);
2400 }
2401 return false;
2402 }
2403
removeEntity(Entity * selected)2404 bool Game::removeEntity(Entity *selected)
2405 {
2406 selected->setState(Entity::STATE_DEAD);
2407 selected->safeKill();
2408 XMLElement *e = this->saveFile->FirstChildElement("Enemy");
2409 while (e)
2410 {
2411 int x = atoi(e->Attribute("x"));
2412 int y = atoi(e->Attribute("y"));
2413 if (int(selected->startPos.x) == x && int(selected->startPos.y) == y)
2414 {
2415 this->saveFile->DeleteChild(e);
2416 //delete e;
2417 return true;
2418 }
2419
2420 e = e->NextSiblingElement("Enemy");
2421 }
2422
2423 for (int i = 0; i < entitySaveData.size(); i++)
2424 {
2425 if (entitySaveData[i].x == int(selected->startPos.x) && entitySaveData[i].y == int(selected->startPos.y))
2426 {
2427 std::vector<EntitySaveData> copy = entitySaveData;
2428 entitySaveData.clear();
2429 for (int j = 0; j < copy.size(); j++)
2430 {
2431 if (j != i)
2432 entitySaveData.push_back(copy[j]);
2433 }
2434 return true;
2435 }
2436 }
2437 return false;
2438 }
2439
removeIngredient(Ingredient * i)2440 void Game::removeIngredient(Ingredient *i)
2441 {
2442 ingredients.remove(i);
2443 }
2444
bindIngredients()2445 void Game::bindIngredients()
2446 {
2447 for (Ingredients::iterator i = ingredients.begin(); i != ingredients.end(); ++ i)
2448 {
2449 Vector v = avatar->position - (*i)->position;
2450 if (!v.isLength2DIn(16))
2451 {
2452 v.setLength2D(500);
2453 (*i)->vel += v;
2454 }
2455 }
2456 }
2457
2458 /*
2459 void Game::getEntityTypeName(int entityType)
2460 {
2461 switch(entityType)
2462 {
2463 case ET_NAUTILUS: return "Nautilus";
2464 case ET_CENTIPEDE: return "Centipede";
2465 case ET_WATERBUG: return "WaterBug";
2466 case ET_CRAWLER: return "Crawler";
2467 case ET_HELLBEASTHEAD: return "HellBeastHead";
2468 case ET_SPINNER: return "Spinner";
2469 case ET_SQUID: return "Squid";
2470 case ET_JELLYFISH: return "JellyFish";
2471 case ET_ROCKHEAD: return "RockHead";
2472 case ET_SPIKE: return "Spike";
2473 case ET_MEGASHRIMP: return "MegaShrimp";
2474 case ET_ZUNNA: return "Zunna";
2475 case ET_PICKUPITEM: return "PickupItem";
2476 case ET_HERETICSKULL: return "HereticSkull";
2477 case ET_RATTLEOYSTER: return "RattleOyster";
2478 case ET_LEACH: return "Leach";
2479 case ET_QUEENHYDRA: return "QueenHydra";
2480 case ET_HYDRALARVA: return "Lumite";
2481 case ET_BARRIER: return "Barrier";
2482 }
2483 }
2484 */
2485
loadEntityTypeList()2486 void Game::loadEntityTypeList()
2487 // and group list!
2488 {
2489 entityTypeList.clear();
2490 InStream in("scripts/entities/entities.txt");
2491 std::string line;
2492 if(!in)
2493 {
2494 exit_error(dsq->continuity.stringBank.get(2008).c_str());
2495 }
2496 while (std::getline(in, line))
2497 {
2498 std::string name, prevGfx;
2499 int idx;
2500 float scale;
2501 std::istringstream is(line);
2502 is >> idx >> name >> prevGfx >> scale;
2503 //errorLog(line);
2504 /*
2505 std::ostringstream os;
2506 os << "adding entity [" << name << "] idx[" << idx << "] prevGfx [" << prevGfx << "] scale [" << scale << "]";
2507 debugLog(os.str());
2508 */
2509 entityTypeList.push_back(EntityClass(name, 1, idx, prevGfx, scale));
2510 }
2511 in.close();
2512
2513 #ifdef AQUARIA_BUILD_SCENEEDITOR
2514 entityGroups.clear();
2515
2516 std::string fn = "scripts/entities/entitygroups.txt";
2517 if (dsq->mod.isActive())
2518 {
2519 fn = dsq->mod.getPath() + "entitygroups.txt";
2520 }
2521
2522 InStream in2(fn.c_str());
2523
2524 int curGroup=0;
2525 while (std::getline(in2, line))
2526 {
2527 if (line.find("GROUP:")!=std::string::npos)
2528 {
2529 line = line.substr(6, line.size());
2530 //debugLog("****** NEWGROUP: " + line);
2531 EntityGroup newGroup;
2532 newGroup.name = line;
2533 //entityGroups[line] = newGroup;
2534 //
2535 entityGroups.push_back(newGroup);
2536 curGroup = entityGroups.size()-1;
2537 }
2538 else if (!line.empty())
2539 {
2540 EntityGroupEntity ent;
2541 std::istringstream is(line);
2542 std::string addLine, graphic;
2543 is >> ent.name >> ent.gfx;
2544 stringToLower(ent.name);
2545 //debugLog("**adding: " + addLine);
2546 entityGroups[curGroup].entities.push_back(ent);
2547 }
2548 }
2549 in2.close();
2550
2551 game->sceneEditor.entityPageNum = 0;
2552 //game->sceneEditor.page = entityGroups.begin();
2553 #endif
2554 }
2555
getEntityClassForEntityType(const std::string & type)2556 EntityClass *Game::getEntityClassForEntityType(const std::string &type)
2557 {
2558 for (int i = 0; i < entityTypeList.size(); i++)
2559 {
2560 /*
2561 std::ostringstream os;
2562 os << "Comparing entityTypeList [" << entityTypeList[i].name << "] with type [" << type << "]";
2563 debugLog(os.str());
2564 */
2565 if (nocasecmp(entityTypeList[i].name, type)==0)
2566 return &entityTypeList[i];
2567 }
2568 return 0;
2569 }
2570
getIdxForEntityType(std::string type)2571 int Game::getIdxForEntityType(std::string type)
2572 {
2573 //if (!type.empty() && type[0] == '@') return -1;
2574
2575 for (int i = 0; i < entityTypeList.size(); i++)
2576 {
2577 if (nocasecmp(entityTypeList[i].name, type)==0)
2578 return entityTypeList[i].idx;
2579 }
2580 return -1;
2581 }
2582
createEntity(int idx,int id,Vector position,int rot,bool createSaveData,std::string name,EntityType et,bool doPostInit)2583 Entity *Game::createEntity(int idx, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit)
2584 {
2585 std::string type;
2586 for (int i = 0; i < dsq->game->entityTypeList.size(); i++)
2587 {
2588 EntityClass *ec = &dsq->game->entityTypeList[i];
2589 if (ec->idx == idx)
2590 {
2591 type = ec->name;
2592 return createEntity(type, id, position, rot, createSaveData, name, et, doPostInit);
2593 }
2594 }
2595 return 0;
2596 }
2597
2598 // ensure a limit of entity types in the current level
2599 // older entities with be culled if state is set to 0
2600 // otherwise, the older entities will have the state set
ensureLimit(Entity * e,int num,int state)2601 void Game::ensureLimit(Entity *e, int num, int state)
2602 {
2603 int idx = e->entityTypeIdx;
2604 int c = 0;
2605 std::list<Entity*> entityList;
2606 FOR_ENTITIES(i)
2607 {
2608 if ((*i)->entityTypeIdx == idx && (state == 0 || (*i)->getState() != state))
2609 {
2610 entityList.push_back(*i);
2611 c++;
2612 }
2613 }
2614
2615 int numDelete = c-(num+1);
2616 if (numDelete >= 0)
2617 {
2618 for (std::list<Entity*>::iterator i = entityList.begin(); i != entityList.end(); i++)
2619 {
2620 if (state == 0)
2621 (*i)->safeKill();
2622 else
2623 (*i)->setState(state);
2624 numDelete--;
2625 if (numDelete <= 0)
2626 break;
2627 }
2628 }
2629 }
2630
establishEntity(Entity * e,int id,Vector position,int rot,bool createSaveData,std::string name,EntityType et,bool doPostInit)2631 Entity* Game::establishEntity(Entity *e, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit)
2632 {
2633 // e->layer must be set BEFORE calling this function!
2634
2635 std::string type = e->name;
2636 stringToLower(type);
2637
2638
2639
2640 // i'm thinking this *should* hold up for new files
2641 // it will mess up if you're importing an old file
2642 // the logic being that you're not going to load in an non-ID-specified entity in new files
2643 // so assignUniqueID should never be called
2644 // so what i'm going to do is have it bitch
2645
2646 // note that when not loading a scene, it is valid to call assignUniqueID here
2647 if (id != 0)
2648 {
2649 e->setID(id);
2650 }
2651 else
2652 {
2653 if (loadingScene)
2654 {
2655 std::ostringstream os;
2656 os << "ERROR: Assigning Unique ID to a loaded Entity... if this is called from loadScene then Entity IDs may be invalid";
2657 os << "\nEntityName: " << e->name;
2658 errorLog(os.str());
2659 }
2660 else
2661 {
2662 e->assignUniqueID();
2663 }
2664 }
2665
2666 // NOTE: init cannot be called after "addRenderObject" for some unknown reason
2667 e->init();
2668
2669 Vector usePos = position;
2670 e->startPos = usePos;
2671 if (!name.empty())
2672 e->name = name;
2673
2674 e->rotation.z = rot;
2675
2676 int idx = getIdxForEntityType(type);
2677 e->entityTypeIdx = idx;
2678
2679
2680 if (createSaveData)
2681 {
2682 int idx = dsq->game->getIdxForEntityType(type);
2683 entitySaveData.push_back(EntitySaveData(e, idx, usePos.x, usePos.y, rot, e->getID(), e->name));
2684 }
2685
2686 addRenderObject(e, e->layer);
2687
2688 if (doPostInit)
2689 {
2690 e->postInit();
2691 }
2692
2693 return e;
2694 }
2695
createEntity(const std::string & t,int id,Vector position,int rot,bool createSaveData,std::string name,EntityType et,bool doPostInit)2696 Entity *Game::createEntity(const std::string &t, int id, Vector position, int rot, bool createSaveData, std::string name, EntityType et, bool doPostInit)
2697 {
2698 std::string type = t;
2699 stringToLower(type);
2700
2701 ScriptedEntity *e;
2702
2703 e = new ScriptedEntity(type, position, et);
2704
2705
2706 return establishEntity(e, id, position, rot, createSaveData, name, et, doPostInit);
2707 }
2708
initEntities()2709 void Game::initEntities()
2710 {
2711 FOR_ENTITIES(i)
2712 {
2713 Entity *e = *i;
2714 if (e)
2715 {
2716 e->init();
2717 }
2718 }
2719 }
2720
assignEntitiesUniqueIDs()2721 void Game::assignEntitiesUniqueIDs()
2722 {
2723 FOR_ENTITIES(i)
2724 {
2725 Entity *e = *i;
2726 if (e && e->entityID == 0)
2727 {
2728 e->assignUniqueID();
2729 }
2730 }
2731
2732 }
2733
getEntitySaveDataForEntity(Entity * e,Vector pos)2734 EntitySaveData *Game::getEntitySaveDataForEntity(Entity *e, Vector pos)
2735 {
2736
2737 for (int i = 0; i < entitySaveData.size(); i++)
2738 {
2739 if (entitySaveData[i].e == e)
2740 {
2741 return &entitySaveData[i];
2742 }
2743 /*
2744 if (entitySaveData[i].x == int(e->startPos.x) && entitySaveData[i].y == int(e->startPos.y))
2745 {
2746 if (entitySaveData[i].idx == e->entityTypeIdx)
2747 {
2748 debugLog("found entity");
2749 return &entitySaveData[i];
2750 }
2751 }
2752 */
2753 }
2754 return 0;
2755 }
2756
setTimerTextAlpha(float a,float t)2757 void Game::setTimerTextAlpha(float a, float t)
2758 {
2759 timerText->alpha.interpolateTo(a, t);
2760 }
2761
setTimerText(float time)2762 void Game::setTimerText(float time)
2763 {
2764 std::ostringstream os;
2765 int mins = int(time/60);
2766 int secs = time - (mins*60);
2767 os << mins;
2768 if (getTimer() > 0.5f)
2769 os << ":";
2770 else
2771 os << ".";
2772 if (secs < 10)
2773 os << "0";
2774 os << secs;
2775 timerText->setText(os.str());
2776 }
2777
generateCollisionMask(Quad * q,float overrideCollideRadius)2778 void Game::generateCollisionMask(Quad *q, float overrideCollideRadius /* = 0 */)
2779 {
2780 #ifdef BBGE_BUILD_OPENGL
2781 if (q->texture)
2782 {
2783 q->collidePosition = Vector(0,0,0);
2784 if (overrideCollideRadius)
2785 q->collideRadius = overrideCollideRadius;
2786 else
2787 q->collideRadius = TILE_SIZE/2;
2788 q->collisionMask.clear();
2789 TileVector tpos(q->position);
2790 int widthscale = q->getWidth()*q->scale.x;
2791 int heightscale = q->getHeight()*q->scale.y;
2792 int w2 = widthscale/2;
2793 int h2 = heightscale/2;
2794 w2/=TILE_SIZE;
2795 h2/=TILE_SIZE;
2796 tpos.x -= w2;
2797 tpos.y -= h2;
2798
2799 int w = 0, h = 0;
2800 unsigned int size = 0;
2801 unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
2802 if (!data)
2803 {
2804 debugLog("Failed to get buffer in Game::generateCollisionMask()");
2805 return;
2806 }
2807
2808 q->collisionMaskRadius = 0;
2809
2810 Vector collisionMaskHalfVector = Vector(q->getWidth()/2, q->getHeight()/2);
2811
2812 int szx = TILE_SIZE/q->scale.x;
2813 int szy = TILE_SIZE/q->scale.y;
2814 if (szx < 1) szx = 1;
2815 if (szy < 1) szy = 1;
2816
2817 for (int tx = 0; tx < widthscale; tx+=TILE_SIZE)
2818 {
2819 for (int ty = 0; ty < heightscale; ty+=TILE_SIZE)
2820 {
2821 int num = 0;
2822
2823 for (int x = 0; x < szx; x++)
2824 {
2825 for (int y = 0; y < szy; y++)
2826 {
2827 // starting position =
2828 // tx / scale.x
2829 unsigned int px = int(tx/q->scale.x) + x;
2830 unsigned int py = int(ty/q->scale.y) + y;
2831 if (px < unsigned(w) && py < unsigned(h))
2832 {
2833 unsigned int p = (py*unsigned(w)*4) + (px*4) + 3; // position of alpha component
2834 if (p < size && data[p] >= 250)
2835 {
2836 num ++;
2837 }
2838 }
2839 }
2840 }
2841 if (num >= int((szx*szy)*0.25f))
2842 {
2843 TileVector tile(int((tx+TILE_SIZE/2)/TILE_SIZE), int((ty+TILE_SIZE/2)/TILE_SIZE));
2844 // + Vector(0,TILE_SIZE)
2845 q->collisionMask.push_back(tile.worldVector() - collisionMaskHalfVector);
2846 }
2847 }
2848 }
2849
2850 q->collisionMaskRadius = 512;
2851
2852 free(data);
2853
2854
2855 /*
2856 for (int i = 0; i < q->collisionMask.size(); i++)
2857 {
2858 float xsz = q->collisionMask[i].x;
2859 float ysz = q->collisionMask[i].y;
2860 if (xsz < 0) xsz = -xsz;
2861 if (ysz < 0) ysz = -ysz;
2862 if (xsz > q->collisionMaskRadius)
2863 q->collisionMaskRadius = xsz;
2864 if (ysz > q->collisionMaskRadius)
2865 q->collisionMaskRadius = ysz;
2866 }
2867 q->collisionMaskRadius += TILE_SIZE/2;
2868 */
2869 /*
2870 if (w2 > h2)
2871 q->collisionMaskRadius = w2*2;
2872 else
2873 q->collisionMaskRadius = h2*2;
2874 */
2875 //q->collisionMaskRadius = sqrtf(sqr(w2)+sqr(h2));
2876
2877 /*
2878 int rot = rotation.z;
2879 while (rot > 360)
2880 rot -= 360;
2881 while (rot < 0)
2882 rot += 360;
2883 */
2884 }
2885 #endif
2886 }
2887
addPath(Path * p)2888 void Game::addPath(Path *p)
2889 {
2890 paths.push_back(p);
2891 if (p->pathType >= 0 && p->pathType < PATH_MAX)
2892 {
2893 p->nextOfType = firstPathOfType[p->pathType];
2894 firstPathOfType[p->pathType] = p;
2895 }
2896 }
2897
removePath(int idx)2898 void Game::removePath(int idx)
2899 {
2900 if (idx >= 0 && idx < paths.size()) paths[idx]->destroy();
2901 std::vector<Path*> copy = this->paths;
2902 clearPaths();
2903 for (int i = 0; i < copy.size(); i++)
2904 {
2905 if (i != idx)
2906 addPath(copy[i]);
2907 }
2908 }
2909
clearPaths()2910 void Game::clearPaths()
2911 {
2912 paths.clear();
2913 for (int i = 0; i < PATH_MAX; i++)
2914 firstPathOfType[i] = 0;
2915 }
2916
getIndexOfPath(Path * p)2917 int Game::getIndexOfPath(Path *p)
2918 {
2919 for (int i = 0; i < paths.size(); i++)
2920 {
2921 if (paths[i] == p)
2922 return i;
2923 }
2924 return -1;
2925 }
2926
getPathAtCursor()2927 Path *Game::getPathAtCursor()
2928 {
2929 return getNearestPath(dsq->getGameCursorPosition(), "");
2930 /*
2931 int range = 128;
2932 int sz = paths.size();
2933 for (int i = 0; i < sz; i++)
2934 {
2935 Path *p = &(paths[i]);
2936 if (!p->nodes.empty())
2937 {
2938 int dist = (p->nodes[0].position - dsq->getGameCursorPosition()).getSquaredLength2D();
2939 if (dist < sqr(range))
2940 {
2941 return p;
2942 }
2943 }
2944 }
2945 return 0;
2946 */
2947 }
2948
getScriptedPathAtCursor(bool withAct)2949 Path *Game::getScriptedPathAtCursor(bool withAct)
2950 {
2951 //int range = 64;
2952 int sz = paths.size();
2953 for (int i = 0; i < sz; i++)
2954 {
2955 Path *p = (paths[i]);
2956 if (!p->nodes.empty() && p->hasScript())
2957 {
2958 if (!withAct || p->cursorActivation)
2959 {
2960 if (p->isCoordinateInside(dsq->getGameCursorPosition()))
2961 {
2962 return p;
2963 }
2964 }
2965 /*
2966 int dist = (p->nodes[0].position - dsq->getGameCursorPosition()).getSquaredLength2D();
2967 if (dist < sqr(range))
2968 {
2969 return p;
2970 }
2971 */
2972 }
2973 }
2974 return 0;
2975 }
2976
getNearestPath(const Vector & pos,const std::string & s,const Path * ignore)2977 Path *Game::getNearestPath(const Vector &pos, const std::string &s, const Path *ignore)
2978 {
2979 Path *closest = 0;
2980 float smallestDist = HUGE_VALF;
2981 std::string st = s;
2982 stringToLower(st);
2983 for (int i = 0; i < dsq->game->paths.size(); i++)
2984 {
2985 Path *cp = dsq->game->paths[i];
2986 if (cp != ignore && !cp->nodes.empty() && (st.empty() || st == cp->label))
2987 {
2988 const Vector v = cp->nodes[0].position - pos;
2989 const float dist = v.getSquaredLength2D();
2990 if (dist < smallestDist)
2991 {
2992 smallestDist = dist;
2993 closest = cp;
2994 }
2995 }
2996 }
2997 return closest;
2998 }
2999
getNearestPath(const Vector & pos,PathType pathType)3000 Path *Game::getNearestPath(const Vector &pos, PathType pathType)
3001 {
3002 Path *closest = 0;
3003 float smallestDist = HUGE_VALF;
3004 for (Path *cp = dsq->game->getFirstPathOfType(pathType); cp; cp = cp->nextOfType)
3005 {
3006 if (!cp->nodes.empty())
3007 {
3008 const Vector v = cp->nodes[0].position - pos;
3009 const float dist = v.getSquaredLength2D();
3010 if (dist < smallestDist)
3011 {
3012 smallestDist = dist;
3013 closest = cp;
3014 }
3015 }
3016 }
3017 return closest;
3018 }
3019
getNearestPath(Path * p,std::string s)3020 Path *Game::getNearestPath(Path *p, std::string s)
3021 {
3022 if (p->nodes.empty()) return 0;
3023
3024 return getNearestPath(p->nodes[0].position, s);
3025 }
3026
getPathByName(std::string name)3027 Path *Game::getPathByName(std::string name)
3028 {
3029 stringToLowerUserData(name);
3030 for (int i = 0; i < paths.size(); i++)
3031 {
3032 if (paths[i]->label == name)
3033 return paths[i];
3034 }
3035 return 0;
3036 }
3037
3038
addKeyConfigLine(RenderObject * group,const std::string & label,const std::string & actionInputName,int y,int l1,int l2,int l3)3039 void Game::addKeyConfigLine(RenderObject *group, const std::string &label, const std::string &actionInputName, int y, int l1, int l2, int l3)
3040 {
3041 //DebugFont *lb = new DebugFont(6, label);
3042 TTFText *lb = new TTFText(&dsq->fontArialSmallest);
3043 lb->setText(label);
3044 lb->position = Vector(140,y);
3045 group->addChild(lb, PM_POINTER);
3046
3047 AquariaKeyConfig *k1 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 0);
3048 k1->position = Vector(350,y);
3049 k1->setLock(l1);
3050 group->addChild(k1, PM_POINTER);
3051
3052 AquariaKeyConfig *k2 = new AquariaKeyConfig(actionInputName, INPUTSET_KEY, 1);
3053 k2->position = Vector(475,y);
3054 k2->setLock(l2);
3055 group->addChild(k2, PM_POINTER);
3056
3057 AquariaKeyConfig *j1 = new AquariaKeyConfig(actionInputName, INPUTSET_JOY, 0);
3058 j1->position = Vector(600,y);
3059 j1->setLock(l3);
3060 group->addChild(j1, PM_POINTER);
3061
3062 k1->setDirMove(DIR_RIGHT, k2);
3063 k2->setDirMove(DIR_RIGHT, j1);
3064
3065 j1->setDirMove(DIR_LEFT, k2);
3066 k2->setDirMove(DIR_LEFT, k1);
3067 }
3068
addAxesConfigLine(RenderObject * group,const std::string & label,const std::string & actionInputName,int y,int offx)3069 AquariaKeyConfig *Game::addAxesConfigLine(RenderObject *group, const std::string &label, const std::string &actionInputName, int y, int offx)
3070 {
3071 /// DebugFont *lb = new DebugFont(6, label);
3072 TTFText *lb = new TTFText(&dsq->fontArialSmallest);
3073 lb->setText(label);
3074 lb->position = Vector(140+offx, y);
3075 group->addChild(lb, PM_POINTER);
3076
3077 AquariaKeyConfig *i1 = new AquariaKeyConfig(actionInputName, INPUTSET_OTHER, 0);
3078 i1->position = Vector(140+80+offx,y);
3079 //i1->setLock(l1);
3080 group->addChild(i1, PM_POINTER);
3081
3082 i1->setDirMove(DIR_RIGHT, 0);
3083 i1->setDirMove(DIR_LEFT, 0);
3084
3085 return i1;
3086 }
3087
doFlagCheck(const std::string & flagCheck,FlagCheckType type,bool lastTruth)3088 bool Game::doFlagCheck(const std::string &flagCheck, FlagCheckType type, bool lastTruth)
3089 {
3090 if (!flagCheck.empty())
3091 {
3092 std::string flagName, comparison, next;
3093 int value=0;
3094 std::istringstream is(flagCheck);
3095 is >> flagName >> comparison >> value >> next;
3096
3097 bool truth=false;
3098 if (comparison == "==")
3099 {
3100 if (dsq->continuity.getFlag(flagName) == value) truth = true;
3101 }
3102 else if (comparison == "<")
3103 {
3104 if (dsq->continuity.getFlag(flagName) < value) truth = true;
3105 }
3106 else if (comparison == ">")
3107 {
3108 if (dsq->continuity.getFlag(flagName) > value) truth = true;
3109 }
3110 else if (comparison == "<=")
3111 {
3112 if (dsq->continuity.getFlag(flagName) <= value) truth = true;
3113 }
3114 else if (comparison == ">=")
3115 {
3116 if (dsq->continuity.getFlag(flagName) >= value) truth = true;
3117 }
3118
3119 if (type == AND)
3120 {
3121 truth = (lastTruth && truth);
3122 }
3123 else if (type == OR)
3124 {
3125 truth = (lastTruth || truth);
3126 }
3127
3128 if (next == "AND")
3129 {
3130 std::string restOfIt;
3131 std::getline(is, restOfIt);
3132 return doFlagCheck(restOfIt, AND, truth);
3133 }
3134 else if (next == "OR")
3135 {
3136 std::string restOfIt;
3137 std::getline(is, restOfIt);
3138 return doFlagCheck(restOfIt, OR, truth);
3139 }
3140
3141 return truth;
3142 }
3143 return true;
3144 }
3145
switchToSongMenu()3146 void Game::switchToSongMenu()
3147 {
3148 dsq->screenTransition->capture();
3149
3150 toggleOptionsMenu(false);
3151 toggleFoodMenu(false);
3152 togglePetMenu(false);
3153 toggleTreasureMenu(false);
3154
3155 toggleMainMenu(true);
3156
3157 dsq->screenTransition->transition(MENUPAGETRANSTIME);
3158 }
3159
switchToFoodMenu()3160 void Game::switchToFoodMenu()
3161 {
3162 dsq->screenTransition->capture();
3163
3164 toggleOptionsMenu(false);
3165 togglePetMenu(false);
3166 toggleMainMenu(false);
3167 toggleTreasureMenu(false);
3168
3169 toggleFoodMenu(true);
3170 dsq->screenTransition->transition(MENUPAGETRANSTIME);
3171 }
3172
switchToPetMenu()3173 void Game::switchToPetMenu()
3174 {
3175 dsq->screenTransition->capture();
3176
3177 toggleOptionsMenu(false);
3178 toggleFoodMenu(false);
3179 toggleMainMenu(false);
3180 toggleTreasureMenu(false);
3181
3182 togglePetMenu(true);
3183 dsq->screenTransition->transition(MENUPAGETRANSTIME);
3184 }
3185
switchToTreasureMenu()3186 void Game::switchToTreasureMenu()
3187 {
3188 dsq->screenTransition->capture();
3189
3190 toggleOptionsMenu(false);
3191 toggleFoodMenu(false);
3192 toggleMainMenu(false);
3193 togglePetMenu(false);
3194
3195 toggleTreasureMenu(true);
3196 dsq->screenTransition->transition(MENUPAGETRANSTIME);
3197 }
3198
3199 /*
3200 IET_INVINCIBLE
3201 IET_HP
3202 IET_MAXHP
3203 IET_DEFENSE
3204 IET_SPEED
3205 IET_REGEN
3206 IET_ENERGY
3207 IET_BLIND
3208 IET_LIGHT
3209 IET_PETPOWER
3210 IET_WEB
3211 IET_LI
3212 IET_FISHPOISON
3213 IET_BITE
3214 IET_EAT
3215 IET_YUM
3216 IET_TRIP
3217 IET_RANDOM
3218 IET_POISON
3219 IET_ALLSTATUS
3220 */
3221
3222 typedef std::vector<IngredientData> IngVec;
3223
sortFood()3224 void Game::sortFood()
3225 {
3226 /*
3227 if (dsq->continuity.foodSortType == FOODSORT_UNSORTED)
3228 {
3229 if (dsq->continuity.sortByUnsort.empty())
3230 for (int i = 0; i < dsq->continuity.ingredients.size(); i++)
3231 dsq->continuity.sortByUnsort.push_back(FoodSortOrder(IT_NONE, IET_NONE, dsq->continuity.ingredients[i].name));
3232 }
3233 */
3234
3235 std::vector<std::string> foodHolderNames;
3236 foodHolderNames.resize(foodHolders.size());
3237
3238 for (int i = 0; i < foodHolders.size(); i++) {
3239 IngredientData *ing = foodHolders[i]->getIngredient();
3240 if (ing) {
3241 foodHolderNames[i] = ing->name;
3242 //errorLog(foodHolderNames[i]);
3243 //foodHolders[i]->setIngredient(0);
3244 }
3245 }
3246
3247 dsq->continuity.foodSortType++;
3248 if (dsq->continuity.foodSortType >= MAX_FOODSORT)
3249 dsq->continuity.foodSortType = 0;
3250
3251 dsq->continuity.sortFood();
3252
3253 // rebuild the page
3254
3255 refreshFoodSlots(false);
3256
3257 /*
3258 toggleFoodMenu(false);
3259 toggleFoodMenu(true);
3260 */
3261
3262 dsq->sound->playSfx("shuffle");
3263 dsq->sound->playSfx("menu-switch", 0.5);
3264 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
3265
3266 for (int i = 0; i < foodHolders.size(); i++) {
3267 if (!foodHolderNames[i].empty()) {
3268 IngredientData *ing = dsq->continuity.getIngredientHeldByName(foodHolderNames[i]);
3269 foodHolders[i]->setIngredient(ing, false);
3270
3271 //foodHolders[i]->setIngredient(dsq->continuity.getIngredientByName(foodHolderNames[i]));
3272 /*
3273 if (!foodHolders[i]->foodHolderIngredient) {
3274 errorLog("not found");
3275 }
3276 else {
3277 std::ostringstream os;
3278 os << "get: " << foodHolders[i]->foodHolderIngredient->name;
3279 errorLog(os.str());
3280 }
3281 */
3282 }
3283 }
3284 }
3285
createInGameMenu()3286 void Game::createInGameMenu()
3287 {
3288 float menuz = 4;
3289 int i = 0;
3290
3291
3292 menuBg = new Quad;
3293 menuBg->setTexture("menu");
3294 //menuBg->setWidthHeight(800);
3295 //menuBg->scale = Vector(800.0f/1024.0f, 800.0f/1024.0f);
3296 menuBgScale = Vector(800.0f/1024.0f, 800.0f/1024.0f);
3297 menuBg->position = Vector(400,300,menuz);
3298 menuBg->followCamera = 1;
3299 //menuBg->shareAlphaWithChildren=true;
3300 addRenderObject(menuBg, LR_MENU);
3301
3302
3303 menuBg2 = new Quad;
3304 menuBg2->setTexture("menu2");
3305 menuBg2->position = Vector(0, 240);
3306 menuBg->addChild(menuBg2, PM_POINTER);
3307
3308 float scale = menuBg->scale.x;
3309 /*
3310 songDescription = new BitmapText(&dsq->font);
3311 songDescription->position = Vector(0,100);
3312 songDescription->parentManagedPointer = 1;
3313 menuBg->addChild(songDescription);
3314 */
3315
3316 options = new Quad;
3317
3318 options->renderQuad = false;
3319
3320 int sliderx = 250, slidery = 160, sliderd = 26;
3321 int checkx=660, checky = 160, checkd = 26;
3322
3323 Quad *audio = new Quad("gui/audiovisual", Vector(200, 125));
3324 options->addChild(audio, PM_POINTER);
3325
3326 Quad *controls = new Quad("gui/controls", Vector(600, 125));
3327 options->addChild(controls, PM_POINTER);
3328
3329 /*
3330 Quad *visual = new Quad("gui/visual", Vector(170, 300));
3331 visual->parentManagedPointer = 1;
3332 options->addChild(visual);
3333 */
3334
3335 /*
3336 Quad *blurEffectsLabel = new Quad("gui/blurEffectsLabel.png", visual->position + Vector(-20,40));
3337 blurEffectsLabel->parentManagedPointer = 1;
3338 options->addChild(blurEffectsLabel);
3339 */
3340
3341 /*
3342 blurEffectsCheck = new AquariaCheckBox();
3343 blurEffectsCheck->position = visual->position + Vector(60, 40);
3344 blurEffectsCheck->parentManagedPointer = 1;
3345 options->addChild(blurEffectsCheck);
3346 */
3347
3348 Quad *controllabels = new Quad("gui/controllabels", Vector(0,0,0));
3349 int w = controllabels->getWidth();
3350 int h = controllabels->getHeight();
3351 controllabels->position = Vector(checkx-16-w/2.0f, checky + h/2.0f - 14);
3352 options->addChild(controllabels, PM_POINTER);
3353
3354
3355
3356 int scheckx=270;
3357 int schecky=315;
3358 int sw,sh;
3359 int voptoffy = 26;
3360
3361 Quad *subtitleslabel = new Quad("gui/subtitles", Vector(0,0,0));
3362 sw = subtitleslabel->getWidth();
3363 sh = subtitleslabel->getHeight();
3364 subtitleslabel->position = Vector(scheckx-16-sw*0.5f, schecky + sh/2.0f - 14);
3365 options->addChild(subtitleslabel, PM_POINTER);
3366
3367 subtitlesCheck = new AquariaCheckBox();
3368 subtitlesCheck->setValue(dsq->user.audio.subtitles);
3369 subtitlesCheck->position = Vector(scheckx,schecky);
3370 options->addChild(subtitlesCheck, PM_POINTER);
3371
3372 Quad *fullscreenLabel = new Quad("gui/fullscreen", Vector(0,0,0));
3373 fullscreenLabel->position = Vector(scheckx-16-sw*0.5f, schecky + voptoffy + sh/2.0f - 14);
3374 options->addChild(fullscreenLabel, PM_POINTER);
3375
3376 fullscreenCheck = new AquariaCheckBox();
3377 fullscreenCheck->setValue(dsq->isFullscreen());
3378 fullscreenCheck->position = Vector(scheckx,schecky + voptoffy);
3379 options->addChild(fullscreenCheck, PM_POINTER);
3380
3381 Quad *resolutionLabel = new Quad("gui/resolution", Vector(0,0,0));
3382 resolutionLabel->position = Vector(160, 260);
3383 options->addChild(resolutionLabel, PM_POINTER);
3384
3385 resBox = new AquariaComboBox(Vector(0.7f, 1.0f));
3386 resBox->position = Vector(196, 285);
3387 for (i = 0; i < core->screenModes.size(); i++)
3388 {
3389 std::ostringstream os;
3390 os << core->screenModes[i].x << "x" << core->screenModes[i].y;
3391 if(core->screenModes[i].hz)
3392 os << " (" << core->screenModes[i].hz << "hz)";
3393 resBox->addItem(os.str());
3394 if (core->screenModes[i].x == dsq->user.video.resx && core->screenModes[i].y == dsq->user.video.resy)
3395 {
3396 resBox->enqueueSelectItem(i);
3397 }
3398 }
3399 options->addChild(resBox, PM_POINTER);
3400
3401 Quad *audiolabels = new Quad("gui/audiolabels", Vector(0,0,0));
3402 w = audiolabels->getWidth();
3403 h = audiolabels->getHeight();
3404 audiolabels->position = Vector(sliderx-64-w/2.0f, slidery + h/2.0f - 14);
3405 options->addChild(audiolabels, PM_POINTER);
3406
3407 musslider = new AquariaSlider();
3408 musslider->setValue(dsq->user.audio.musvol);
3409 musslider->position = Vector(sliderx,slidery+1*sliderd);
3410 options->addChild(musslider, PM_POINTER);
3411
3412 sfxslider = new AquariaSlider();
3413 sfxslider->setValue(dsq->user.audio.sfxvol);
3414 sfxslider->position = Vector(sliderx,slidery);
3415 options->addChild(sfxslider, PM_POINTER);
3416
3417 voxslider = new AquariaSlider();
3418 voxslider->setValue(dsq->user.audio.voxvol);
3419 voxslider->position = Vector(sliderx,slidery+2*sliderd);
3420 options->addChild(voxslider, PM_POINTER);
3421
3422
3423 flipInputButtonsCheck = new AquariaCheckBox();
3424 flipInputButtonsCheck->setValue(dsq->user.control.flipInputButtons);
3425 flipInputButtonsCheck->position = Vector(checkx,checky);
3426 options->addChild(flipInputButtonsCheck, PM_POINTER);
3427
3428 micInputCheck = 0;
3429
3430 toolTipsCheck = new AquariaCheckBox();
3431 toolTipsCheck->setValue(dsq->user.control.toolTipsOn);
3432 toolTipsCheck->position = Vector(checkx,checky+1*checkd);
3433 options->addChild(toolTipsCheck, PM_POINTER);
3434
3435 autoAimCheck = new AquariaCheckBox();
3436 autoAimCheck->setValue(dsq->user.control.autoAim);
3437 autoAimCheck->position = Vector(checkx,checky+2*checkd);
3438 options->addChild(autoAimCheck, PM_POINTER);
3439
3440 targetingCheck = new AquariaCheckBox();
3441 targetingCheck->setValue(dsq->user.control.targeting);
3442 targetingCheck->position = Vector(checkx,checky+3*checkd);
3443 options->addChild(targetingCheck, PM_POINTER);
3444
3445
3446
3447 opt_save = new AquariaMenuItem;
3448 opt_save->useQuad("gui/Apply");
3449 opt_save->useGlow("particles/glow", 100, 50);
3450 opt_save->event.set(MakeFunctionEvent(Game, onOptionsSave));
3451 opt_save->position = opt_save_original;
3452 opt_save->alpha = 0;
3453 addRenderObject(opt_save, LR_MENU);
3454
3455 opt_cancel = new AquariaMenuItem;
3456 opt_cancel->useQuad("gui/Cancel");
3457 opt_cancel->useGlow("particles/glow", 100, 50);
3458 opt_cancel->event.set(MakeFunctionEvent(Game, onOptionsCancel));
3459 opt_cancel->position = opt_cancel_original;
3460 opt_cancel->alpha = 0;
3461 addRenderObject(opt_cancel, LR_MENU);
3462
3463 options->shareAlphaWithChildren = 1;
3464 options->alpha = 0;
3465 options->followCamera = 1;
3466 addRenderObject(options, LR_MENU);
3467
3468 scale = 1;
3469 songSlots.clear();
3470 //songSlots.resize(3);
3471 songSlots.resize(10);
3472 // rewrite this: so you can hide / ignore certain songs, etc
3473 //songSlots.resize(dsq->continuity.getSongBankSize());
3474 //Vector center(-235, -50);
3475 Vector center(-230, -50), rightCenter(230, -50);
3476
3477 energyIdol = new Quad("formupgrades/energyidol-charged", Vector(40,0));
3478 menuBg->addChild(energyIdol, PM_POINTER);
3479
3480 liCrystal = new Quad("gui/li-crystal", Vector(0,0));
3481 menuBg->addChild(liCrystal, PM_POINTER);
3482
3483 songBubbles = new Quad("gui/SongBubbles", Vector(-center.x, center.y));
3484 menuBg->addChild(songBubbles, PM_POINTER);
3485
3486
3487 // Vector(575,250);
3488
3489
3490 songLabel = new BitmapText(&dsq->smallFont);
3491 {
3492 songLabel->alpha = 0;
3493 songLabel->setAlign(ALIGN_CENTER);
3494 songLabel->followCamera = 1;
3495 songLabel->setFontSize(20);
3496 songLabel->position = Vector(-center.x, center.y) + Vector(0, -15); //+ Vector(10, -10);
3497 songLabel->scale = Vector(1.2, 1.2);
3498 }
3499 menuBg->addChild(songLabel, PM_POINTER);
3500
3501
3502
3503
3504 ToolTip *tip = 0;
3505
3506 foodTips.clear();
3507 songTips.clear();
3508 petTips.clear();
3509 treasureTips.clear();
3510
3511 tip = new ToolTip;
3512 tip->alpha = 0;
3513 tip->setCircularAreaFromCenter(worldLeftCenter, 240);
3514 tip->setText(dsq->continuity.stringBank.get(0), Vector(200,450), 350);
3515 addRenderObject(tip, LR_HUD);
3516 foodTips.push_back(tip);
3517
3518
3519 tip = new ToolTip;
3520 tip->alpha = 0;
3521 tip->setCircularAreaFromCenter(worldRightCenter, 240);
3522 tip->setText(dsq->continuity.stringBank.get(1), Vector(600,450), 350);
3523 addRenderObject(tip, LR_HUD);
3524 foodTips.push_back(tip);
3525
3526
3527
3528 tip = new ToolTip;
3529 tip->alpha = 0;
3530 tip->setCircularAreaFromCenter(worldLeftCenter, 240);
3531 tip->setText(dsq->continuity.stringBank.get(14), Vector(200,450), 350);
3532 addRenderObject(tip, LR_HUD);
3533 songTips.push_back(tip);
3534
3535
3536 /*
3537 tip = new ToolTip;
3538 tip->alpha = 0;
3539 tip->setAreaFromCenter(Vector(400,300), 800, 600);
3540 tip->setText(dsq->continuity.stringBank.get(16), Vector(400,300), 400);
3541 addRenderObject(tip, LR_HUD);
3542 petTips.push_back(tip);
3543 */
3544
3545 tip = new ToolTip;
3546 tip->alpha = 0;
3547 tip->setCircularAreaFromCenter(worldLeftCenter, 240);
3548 tip->setText(dsq->continuity.stringBank.get(17), Vector(200,450), 350);
3549 addRenderObject(tip, LR_HUD);
3550 petTips.push_back(tip);
3551
3552 tip = new ToolTip;
3553 tip->alpha = 0;
3554 tip->setAreaFromCenter(Vector(400,350), 150, 50);
3555 tip->setText(dsq->continuity.stringBank.get(15), Vector(400,450), 450);
3556 addRenderObject(tip, LR_HUD);
3557 songTips.push_back(tip);
3558 foodTips.push_back(tip);
3559 petTips.push_back(tip);
3560 treasureTips.push_back(tip);
3561
3562 int radius = 118;
3563 int food = 0;
3564
3565 keyConfigButton = new AquariaMenuItem;
3566 keyConfigButton->useQuad("gui/keyconfig-button");
3567 keyConfigButton->useGlow("particles/glow", 128, 40);
3568 keyConfigButton->position = worldRightCenter + Vector(0, 80);
3569 keyConfigButton->alpha = 0;
3570 keyConfigButton->scale = Vector(0.8, 0.8);
3571 keyConfigButton->event.set(MakeFunctionEvent(Game, onKeyConfig));
3572 //keyConfigButton->setCanDirMove(false);
3573 addRenderObject(keyConfigButton, LR_MENU);
3574
3575
3576
3577 group_keyConfig = new RenderObject;
3578
3579 /*
3580 Quad *kbg = new Quad("gui/keyconfig-menu", Vector(400,300));
3581 kbg->setWidthHeight(800, 800);
3582 group_keyConfig->addChild(kbg);
3583 */
3584
3585 //Quad *kcb = new Quad;
3586 RoundedRect *kcb = new RoundedRect();
3587 //kcb->color = 0;
3588 //kcb->alphaMod = 0.75;
3589 kcb->position = Vector(400,276 - 10);
3590 kcb->setWidthHeight(580, 455, 10);
3591 group_keyConfig->addChild(kcb, PM_POINTER);
3592
3593 int offy = -20;
3594
3595 #define SB(x) dsq->continuity.stringBank.get(x)
3596
3597 TTFText *header_action = new TTFText(&dsq->fontArialSmall);
3598 header_action->setText(SB(2101));
3599 header_action->position = Vector(140, 80+offy);
3600 group_keyConfig->addChild(header_action, PM_POINTER);
3601
3602 TTFText *header_key1 = new TTFText(&dsq->fontArialSmall);
3603 header_key1->setText(SB(2102));
3604 header_key1->position = Vector(350, 80+offy);
3605 header_key1->setAlign(ALIGN_CENTER);
3606 group_keyConfig->addChild(header_key1, PM_POINTER);
3607
3608 TTFText *header_key2 = new TTFText(&dsq->fontArialSmall);
3609 header_key2->setText(SB(2103));
3610 header_key2->position = Vector(475, 80+offy);
3611 header_key2->setAlign(ALIGN_CENTER);
3612 group_keyConfig->addChild(header_key2, PM_POINTER);
3613
3614 TTFText *header_joy = new TTFText(&dsq->fontArialSmall);
3615 header_joy->setText(SB(2104));
3616 header_joy->position = Vector(600, 80+offy);
3617 header_joy->setAlign(ALIGN_CENTER);
3618 group_keyConfig->addChild(header_joy, PM_POINTER);
3619
3620 addKeyConfigLine(group_keyConfig, SB(2105), "lmb", 100+offy, 0, 0, 0);
3621 addKeyConfigLine(group_keyConfig, SB(2106), "rmb", 120+offy, 0, 0, 0);
3622 addKeyConfigLine(group_keyConfig, SB(2107), "PrimaryAction", 140+offy);
3623 addKeyConfigLine(group_keyConfig, SB(2108), "SecondaryAction", 160+offy);
3624 addKeyConfigLine(group_keyConfig, SB(2109), "SwimUp", 180+offy);
3625 addKeyConfigLine(group_keyConfig, SB(2110), "SwimDown", 200+offy);
3626 addKeyConfigLine(group_keyConfig, SB(2111), "SwimLeft", 220+offy);
3627 addKeyConfigLine(group_keyConfig, SB(2112), "SwimRight", 240+offy);
3628 addKeyConfigLine(group_keyConfig, SB(2113), "Roll", 260+offy);
3629 addKeyConfigLine(group_keyConfig, SB(2114), "Revert", 280+offy);
3630 addKeyConfigLine(group_keyConfig, SB(2115), "WorldMap", 300+offy);
3631 addKeyConfigLine(group_keyConfig, SB(2116), "Escape", 320+offy, 1, 0, 0);
3632
3633 AquariaKeyConfig* s1x = addAxesConfigLine(group_keyConfig, SB(2117), "s1ax", 340+offy, 0);
3634 AquariaKeyConfig* s1y = addAxesConfigLine(group_keyConfig, SB(2118), "s1ay", 340+offy, 130);
3635 AquariaKeyConfig* s2x = addAxesConfigLine(group_keyConfig, SB(2119), "s2ax", 340+offy, 260);
3636 AquariaKeyConfig* s2y = addAxesConfigLine(group_keyConfig, SB(2120), "s2ay", 340+offy, 380);
3637
3638 s1x->setDirMove(DIR_LEFT, s1x);
3639 s1x->setDirMove(DIR_RIGHT, s1y);
3640
3641 s1y->setDirMove(DIR_LEFT, s1x);
3642 s1y->setDirMove(DIR_RIGHT, s2x);
3643
3644 s2x->setDirMove(DIR_LEFT, s1y);
3645 s2x->setDirMove(DIR_RIGHT, s2y);
3646
3647 s2y->setDirMove(DIR_LEFT, s2x);
3648 s2y->setDirMove(DIR_RIGHT, s2y);
3649
3650 offy += 20;
3651
3652 addKeyConfigLine(group_keyConfig, SB(2121), "PrevPage", 340+offy);
3653 addKeyConfigLine(group_keyConfig, SB(2122), "NextPage", 360+offy);
3654 addKeyConfigLine(group_keyConfig, SB(2123), "CookFood", 380+offy);
3655 addKeyConfigLine(group_keyConfig, SB(2124), "FoodLeft", 400+offy);
3656 addKeyConfigLine(group_keyConfig, SB(2125), "FoodRight", 420+offy);
3657 addKeyConfigLine(group_keyConfig, SB(2126), "FoodDrop", 440+offy);
3658
3659 addKeyConfigLine(group_keyConfig, SB(2127), "Look", 460+offy);
3660
3661 addKeyConfigLine(group_keyConfig, SB(2128), "ToggleHelp", 480+offy);
3662
3663 #undef SB
3664
3665 group_keyConfig->shareAlphaWithChildren = 1;
3666 group_keyConfig->followCamera = 1;
3667 group_keyConfig->alpha = 0;
3668 group_keyConfig->setHidden(true);
3669
3670 group_keyConfig->position = Vector(0, -40);
3671
3672 addRenderObject(group_keyConfig, LR_OVERLAY);
3673
3674
3675 cook = new AquariaMenuItem;
3676 cook->useQuad("Gui/cook-button");
3677 cook->useGlow("particles/glow", 128, 40);
3678 cook->position = worldRightCenter + Vector(0, -120);
3679 cook->alpha = 0;
3680 cook->scale = Vector(0.8, 0.8);
3681 cook->event.set(MakeFunctionEvent(Game, onCook));
3682 cook->setCanDirMove(false);
3683 addRenderObject(cook, LR_MENU);
3684
3685 foodSort = new AquariaMenuItem;
3686 foodSort->useQuad("gui/sort");
3687 foodSort->useSound("click");
3688 foodSort->useGlow("particles/glow", 32,32);
3689 foodSort->position = worldLeftCenter + Vector(-100, -100);
3690 foodSort->event.set(MakeFunctionEvent(Game, sortFood));
3691 foodSort->alpha = 0;
3692 addRenderObject(foodSort, LR_MENU);
3693
3694 recipes = new AquariaMenuItem;
3695 recipes->useQuad("Gui/recipes-button");
3696 recipes->useGlow("particles/glow", 128, 32);
3697 recipes->position = worldLeftCenter + Vector(-40, 140);
3698 recipes->alpha = 0;
3699 recipes->scale = Vector(0.8, 0.8);
3700 recipes->event.set(MakeFunctionEvent(Game, onRecipes));
3701 addRenderObject(recipes, LR_MENU);
3702
3703 use = new AquariaMenuItem;
3704 use->useQuad("Gui/use-button");
3705 use->useGlow("particles/glow", 128, 64);
3706 use->position = worldRightCenter + Vector(0, -120);
3707 use->alpha = 0;
3708 use->scale = Vector(0.8, 0.8);
3709 use->event.set(MakeFunctionEvent(Game, onUseTreasure));
3710 addRenderObject(use, LR_MENU);
3711
3712 prevFood = new AquariaMenuItem;
3713 prevFood->useQuad("Gui/arrow-left");
3714 prevFood->useSound("click");
3715 prevFood->useGlow("particles/glow", 64, 32);
3716 prevFood->position = worldLeftCenter + Vector(-50, -130);
3717 prevFood->alpha = 0;
3718 prevFood->event.set(MakeFunctionEvent(Game, onPrevFoodPage));
3719 prevFood->scale = Vector(0.6, 0.6);
3720 prevFood->setCanDirMove(false);
3721 addRenderObject(prevFood, LR_MENU);
3722
3723 nextFood = new AquariaMenuItem;
3724 nextFood->useQuad("Gui/arrow-right");
3725 nextFood->useSound("click");
3726 nextFood->useGlow("particles/glow", 64, 32);
3727 nextFood->position = worldLeftCenter + Vector(50, -130);
3728 nextFood->alpha = 0;
3729 nextFood->setCanDirMove(false);
3730 nextFood->event.set(MakeFunctionEvent(Game, onNextFoodPage));
3731 nextFood->scale = Vector(0.6, 0.6);
3732 addRenderObject(nextFood, LR_MENU);
3733
3734 prevTreasure = new AquariaMenuItem;
3735 prevTreasure->useQuad("Gui/arrow-left");
3736 prevTreasure->useSound("click");
3737 prevTreasure->useGlow("particles/glow", 64, 32);
3738 prevTreasure->position = worldLeftCenter + Vector(-50, -130);
3739 prevTreasure->alpha = 0;
3740 prevTreasure->setCanDirMove(false);
3741 prevTreasure->scale = Vector(0.6, 0.6);
3742 prevTreasure->event.set(MakeFunctionEvent(Game, onPrevTreasurePage));
3743 prevTreasure->setCanDirMove(false);
3744 addRenderObject(prevTreasure, LR_MENU);
3745
3746 nextTreasure = new AquariaMenuItem;
3747 nextTreasure->useQuad("Gui/arrow-right");
3748 nextTreasure->useSound("click");
3749 nextTreasure->useGlow("particles/glow", 64, 32);
3750 nextTreasure->position = worldLeftCenter + Vector(50, -130);
3751 nextTreasure->alpha = 0;
3752 nextTreasure->scale = Vector(0.6, 0.6);
3753 nextTreasure->event.set(MakeFunctionEvent(Game, onNextTreasurePage));
3754 nextTreasure->setCanDirMove(false);
3755 addRenderObject(nextTreasure, LR_MENU);
3756
3757 circlePageNum = new BitmapText(&dsq->smallFont);
3758 circlePageNum->color = Vector(0,0,0);
3759 circlePageNum->position = worldLeftCenter + Vector(0, -142);
3760 circlePageNum->alpha = 0;
3761 circlePageNum->followCamera = 1;
3762 addRenderObject(circlePageNum, LR_MENU);
3763
3764 foodHolders.resize(3);
3765 int holders=0;
3766 for (i = 0; i < foodHolders.size(); i++)
3767 {
3768 foodHolders[i] = new FoodHolder(i);
3769 foodHolders[i]->alpha = 0;
3770
3771 float angle = (float(holders)/float(foodHolders.size()))*PI*2;
3772 foodHolders[i]->position = rightCenter + Vector(sinf(angle), cosf(angle))*radius;
3773 holders ++;
3774
3775 menuBg->addChild(foodHolders[i], PM_POINTER);
3776 }
3777
3778 previewRecipe = new Quad;
3779 previewRecipe->alphaMod = 0.75;
3780 previewRecipe->followCamera = 1;
3781 previewRecipe->alpha = 0;
3782 previewRecipe->scale = Vector(0.7, 0.7);
3783 previewRecipe->scale.interpolateTo(Vector(0.9, 0.9), 0.5, -1, 1, 1);
3784 previewRecipe->position = worldRightCenter;
3785 addRenderObject(previewRecipe, LR_MENU);
3786
3787 showRecipe = new Quad();
3788 showRecipe->followCamera = 1;
3789 showRecipe->position = Vector(575,250);
3790 addRenderObject(showRecipe, LR_MENU);
3791
3792 float scrollx = 555;
3793 recipeMenu.scroll = new Quad("gui/recipe-scroll", Vector(scrollx, 200));
3794 recipeMenu.scroll->followCamera = 1;
3795 recipeMenu.scroll->alpha = 0;
3796 addRenderObject(recipeMenu.scroll, LR_RECIPES); // LR_HUD3
3797
3798 recipeMenu.scrollEnd = new Quad("gui/recipe-scroll-end", Vector(scrollx, 400));
3799 recipeMenu.scrollEnd->followCamera = 1;
3800 recipeMenu.scrollEnd->alpha = 0;
3801 addRenderObject(recipeMenu.scrollEnd, LR_RECIPES);
3802
3803 recipeMenu.header = new BitmapText(&dsq->font);
3804 recipeMenu.header->color = 0;
3805 recipeMenu.header->followCamera = 1;
3806 recipeMenu.header->setText(dsq->continuity.stringBank.get(2007));
3807 recipeMenu.header->alpha = 0;
3808 recipeMenu.header->position = Vector(scrollx, 5); //10
3809 addRenderObject(recipeMenu.header, LR_RECIPES);
3810
3811 recipeMenu.page = new BitmapText(&dsq->smallFont);
3812 recipeMenu.page->color = 0;
3813 recipeMenu.page->followCamera = 1;
3814 recipeMenu.page->position = Vector(scrollx, 400);
3815 recipeMenu.page->setText(dsq->continuity.stringBank.get(2006));
3816 recipeMenu.page->alpha = 0;
3817 addRenderObject(recipeMenu.page, LR_RECIPES);
3818
3819 recipeMenu.prevPage = new AquariaMenuItem;
3820 recipeMenu.prevPage->useQuad("Gui/arrow-left");
3821 recipeMenu.prevPage->useSound("click");
3822 recipeMenu.prevPage->useGlow("particles/glow", 64, 32);
3823 recipeMenu.prevPage->position = Vector(scrollx - 150, 410);
3824 recipeMenu.prevPage->alpha = 0;
3825 recipeMenu.prevPage->event.set(MakeFunctionEvent(Game, onPrevRecipePage));
3826 recipeMenu.prevPage->scale = Vector(0.8, 0.8);
3827 addRenderObject(recipeMenu.prevPage, LR_RECIPES);
3828
3829 recipeMenu.nextPage = new AquariaMenuItem;
3830 recipeMenu.nextPage->useQuad("Gui/arrow-right");
3831 recipeMenu.nextPage->useSound("click");
3832 recipeMenu.nextPage->useGlow("particles/glow", 64, 32);
3833 recipeMenu.nextPage->position = Vector(scrollx + 150, 410);
3834 recipeMenu.nextPage->alpha = 0;
3835 recipeMenu.nextPage->event.set(MakeFunctionEvent(Game, onNextRecipePage));
3836 recipeMenu.nextPage->scale = Vector(0.8, 0.8);
3837 addRenderObject(recipeMenu.nextPage, LR_RECIPES);
3838
3839
3840 petSlots.resize(dsq->continuity.petData.size());
3841 for (i = 0; i < petSlots.size(); i++)
3842 {
3843 PetData *p = dsq->continuity.getPetData(i);
3844 if (p)
3845 {
3846 petSlots[i] = new PetSlot(i);
3847 petSlots[i]->alpha = 0;
3848 float angle = (float(i)/float(petSlots.size()))*PI*2;
3849 petSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*(radius*0.9f);
3850 menuBg->addChild(petSlots[i], PM_POINTER);
3851 }
3852 }
3853
3854 foodHolders.resize(4);
3855 foodHolders[3] = new FoodHolder(-1, true);
3856 foodHolders[3]->alpha = 0;
3857 foodHolders[3]->position = rightCenter + Vector(96, 150);
3858 menuBg->addChild(foodHolders[3], PM_POINTER);
3859
3860
3861
3862
3863
3864 int outer = 0;
3865 int inner = 0;
3866 for (i = 0; i < songSlots.size(); i++)
3867 {
3868 songSlots[i] = new SongSlot(i);
3869 float angle = 0;
3870 SongType s = (SongType)dsq->continuity.getSongTypeBySlot(i);
3871 if (dsq->continuity.isSongTypeForm(s))
3872 {
3873 angle = (float(outer)/float(numForms))*PI*2;
3874 songSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*radius;
3875 outer ++;
3876 }
3877 else
3878 {
3879 angle = (float(inner)/float(songSlots.size()-numForms))*PI*2 + PI;
3880 songSlots[i]->position = center + Vector(sinf(angle), cosf(angle))*radius*0.4f;
3881 inner ++;
3882 }
3883 menuBg->addChild(songSlots[i], PM_POINTER);
3884 }
3885 menuSongs = 0;
3886
3887 menuMoney = menuEXP = 0;
3888
3889 menuDescription = new BitmapText(&dsq->smallFont);
3890 menuDescription->setFontSize(14);
3891 menuDescription->position = Vector(400, 450);
3892 menuDescription->setAlign(ALIGN_CENTER);
3893 menuDescription->setWidth(400);
3894 menuDescription->followCamera = 1;
3895 menuDescription->alpha = 0;
3896 addRenderObject(menuDescription, LR_MENU);
3897
3898 currentInventoryPage = 0;
3899
3900 int areYouShim = -25;
3901 eAre = new Quad;
3902 eAre->position = Vector(400,448+areYouShim);
3903 eAre->setTexture("AreYouSure");
3904 eAre->alpha = 0;
3905 eAre->followCamera = 1;
3906 addRenderObject(eAre, LR_MENU);
3907
3908 eYes = new AquariaMenuItem;
3909 eYes->position = Vector(400-100,516+areYouShim);
3910 eYes->useQuad("Yes");
3911 eYes->useGlow("particles/glow", 100, 32);
3912 eYes->event.set(MakeFunctionEvent(Game, onExitCheckYes));
3913 eYes->alpha = 0;
3914 eYes->shareAlpha = 1;
3915 addRenderObject(eYes, LR_MENU);
3916
3917 eNo = new AquariaMenuItem;
3918 eNo->position = Vector(400+100,516+areYouShim);
3919 eNo->useQuad("No");
3920 eNo->useGlow("particles/glow", 100, 32);
3921 eNo->event.set(MakeFunctionEvent(Game, onExitCheckNo));
3922 eNo->alpha = 0;
3923 eNo->shareAlpha = 1;
3924 addRenderObject(eNo, LR_MENU);
3925
3926 eNo->setDirMove(DIR_LEFT, eYes);
3927 eYes->setDirMove(DIR_RIGHT, eNo);
3928
3929
3930
3931 menu.resize(10);
3932 for (i = 0; i < menu.size(); i++)
3933 menu[i] = new AquariaMenuItem;
3934
3935 int ty = 530;
3936 //menu[0]->setLabel("Continue");
3937 menu[0]->event.set(MakeFunctionEvent(Game, onInGameMenuContinue));
3938 menu[0]->useGlow("particles/glow", 200, 100);
3939 //menu[0]->position = Vector(150, 550);
3940 menu[0]->position = Vector(150-30, ty-10);
3941
3942 //menu[1]->setLabel("Exit");
3943 menu[1]->useGlow("particles/glow", 200, 100);
3944 menu[1]->event.set(MakeFunctionEvent(Game, onInGameMenuExit));
3945 //menu[1]->position = Vector(800-150, 550);
3946 //menu[1]->position = Vector(800-150+30, ty);
3947 menu[1]->position = Vector(800-150+20, ty-10);
3948
3949 menu[2]->setLabel("DebugSave");
3950 menu[2]->event.set(MakeFunctionEvent(Game, onDebugSave));
3951 menu[2]->position = Vector(400,ty+60);
3952 if (!dsq->isDeveloperKeys())
3953 menu[2]->position = Vector(400, 12000);
3954 menu[2]->setCanDirMove(false);
3955
3956 menu[3]->event.set(MakeFunctionEvent(Game, onLips));
3957 menu[3]->useGlow("particles/glow", 64, 64);
3958 //menu[0]->position = Vector(150, 550);
3959 menu[3]->position = Vector(400, 195);
3960 menu[3]->setCanDirMove(false);
3961
3962 lips = menu[3];
3963
3964 // options
3965 menu[4]->event.set(MakeFunctionEvent(Game, onOptionsMenu));
3966 menu[4]->useGlow("particles/glow", 200, 32);
3967 menu[4]->position = Vector(400,ty+10);
3968
3969 int gs = 40;
3970
3971 menu[5]->event.set(MakeFunctionEvent(Game, switchToSongMenu));
3972 menu[5]->useQuad("gui/icon-songs");
3973 menu[5]->useGlow("particles/glow", gs, gs);
3974 menu[5]->useSound("Click");
3975 menu[5]->position = Vector(400-60, 350);
3976
3977 menuIconGlow = new Quad("particles/glow", menu[5]->position);
3978 menuIconGlow->alphaMod = 0.4;
3979 menuIconGlow->alpha = 0;
3980 menuIconGlow->setWidthHeight(80, 80);
3981 menuIconGlow->setBlendType(RenderObject::BLEND_ADD);
3982 menuIconGlow->followCamera = 1;
3983 addRenderObject(menuIconGlow, LR_MENU);
3984
3985 menu[6]->event.set(MakeFunctionEvent(Game, switchToFoodMenu));
3986 menu[6]->useQuad("gui/icon-food");
3987 menu[6]->useGlow("particles/glow", gs, gs);
3988 menu[6]->useSound("Click");
3989 menu[6]->position = Vector(400-20, 350);
3990
3991 menu[7]->event.set(MakeFunctionEvent(Game, switchToPetMenu));
3992 menu[7]->useQuad("gui/icon-pets");
3993 menu[7]->useGlow("particles/glow", gs, gs);
3994 menu[7]->useSound("Click");
3995 menu[7]->position = Vector(400+20, 350);
3996
3997 menu[8]->event.set(MakeFunctionEvent(Game, switchToTreasureMenu));
3998 menu[8]->useQuad("gui/icon-treasures");
3999 menu[8]->useGlow("particles/glow", gs, gs);
4000 menu[8]->useSound("Click");
4001 menu[8]->position = Vector(400+60, 350);
4002
4003 menu[9]->event.set(MakeFunctionEvent(Game, toggleHelpScreen));
4004 menu[9]->useQuad("gui/icon-help");
4005 menu[9]->useGlow("particles/glow", gs, gs);
4006 menu[9]->useSound("Click");
4007 menu[9]->position = Vector(400+60*3, 410);
4008
4009 /*
4010 menu[9]->event.set(MakeFunctionEvent(Game, sortFood));
4011 menu[9]->setLabel("sort food");
4012 menu[9]->position = Vector(100,100);
4013 */
4014
4015 for (i = 0; i < menu.size(); i++)
4016 {
4017 addRenderObject(menu[i], LR_MENU);
4018 menu[i]->alpha = 0;
4019 }
4020
4021 ((AquariaMenuItem*)menu[5])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[0]));
4022 ((AquariaMenuItem*)menu[6])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[4]));
4023 ((AquariaMenuItem*)menu[7])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[4]));
4024 ((AquariaMenuItem*)menu[8])->setDirMove(DIR_DOWN, ((AquariaMenuItem*)menu[1]));
4025
4026 ((AquariaMenuItem*)menu[0])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[5]));
4027 ((AquariaMenuItem*)menu[1])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[8]));
4028
4029 ((AquariaMenuItem*)menu[4])->setDirMove(DIR_UP, ((AquariaMenuItem*)menu[6]));
4030
4031
4032
4033 // ---------- FOOD MENU
4034
4035 foodSlots.resize(foodPageSize);
4036
4037 Vector worldCenter(222, 252);
4038
4039 int foodSlotRadius = 96;
4040 for (i = 0; i < foodSlots.size(); i++)
4041 {
4042 foodSlots[i] = new FoodSlot(i);
4043
4044 float angle = (float(food)/float(foodSlots.size()))*PI*2;
4045 foodSlots[i]->position = worldCenter + Vector(sinf(angle), cosf(angle))*foodSlotRadius;
4046
4047 foodSlots[i]->setOriginalPosition(foodSlots[i]->position);
4048
4049 food ++;
4050
4051 foodSlots[i]->alphaMod = 0;
4052
4053 foodSlots[i]->followCamera = 1;
4054
4055 foodSlots[i]->scaleFactor = 0.75;
4056
4057 //foodSlots[i]->parentManagedPointer = 1;
4058 //menuBg->addChild(foodSlots[i]);
4059 //foodSlots[i]->position = menuBg->getWorldCollidePosition(foodSlots[i]->position);
4060 addRenderObject(foodSlots[i], LR_HUD2);
4061 }
4062
4063
4064 foodLabel = new BitmapText(&dsq->smallFont);
4065 {
4066 foodLabel->alpha = 0;
4067 foodLabel->setAlign(ALIGN_CENTER);
4068 foodLabel->followCamera = 1;
4069 foodLabel->setFontSize(20);
4070 foodLabel->position = center - Vector(0, 16) + Vector(0,-32);
4071 foodLabel->scale = Vector(1, 1);
4072 }
4073 menuBg->addChild(foodLabel, PM_POINTER);
4074
4075 foodDescription = new BitmapText(&dsq->smallFont);
4076 {
4077 foodDescription->alpha = 0;
4078 foodDescription->setAlign(ALIGN_CENTER);
4079 foodDescription->followCamera = 1;
4080 foodDescription->position = center + Vector(0, 8) + Vector(0,-32);
4081 foodDescription->scale = Vector(0.8, 0.8);
4082
4083 foodDescription->setWidth(240);
4084 }
4085 menuBg->addChild(foodDescription, PM_POINTER);
4086
4087
4088 // ---------- TREASURES
4089
4090
4091 int treasureSlotRadius = 96;
4092
4093 treasureSlots.resize(treasurePageSize);
4094
4095 for (i = 0; i < treasureSlots.size(); i++)
4096 {
4097 treasureSlots[i] = new TreasureSlot(i);
4098
4099
4100 float angle = (float(i)/float(treasureSlots.size()))*PI*2;
4101 treasureSlots[i]->position = worldCenter + Vector(sinf(angle), cosf(angle))*treasureSlotRadius;
4102
4103 treasureSlots[i]->alphaMod = 0;
4104
4105 treasureSlots[i]->followCamera = 1;
4106
4107 //treasureSlots[i]->scaleFactor = 0.75;
4108
4109 addRenderObject(treasureSlots[i], LR_MENU);
4110 }
4111
4112 treasureLabel = new BitmapText(&dsq->smallFont);
4113 {
4114 treasureLabel->alpha = 0;
4115 treasureLabel->setAlign(ALIGN_CENTER);
4116 treasureLabel->followCamera = 1;
4117 treasureLabel->setFontSize(20);
4118 treasureLabel->position = center - Vector(0, 16);
4119 treasureLabel->scale = Vector(1, 1);
4120 }
4121 menuBg->addChild(treasureLabel, PM_POINTER);
4122
4123 treasureDescription = new ToolTip();
4124 treasureDescription->alpha = 0;
4125 treasureDescription->setAreaFromCenter(Vector(400,200), 800, 400);
4126 treasureDescription->required = true;
4127 addRenderObject(treasureDescription, LR_HUD);
4128
4129 foodTips.push_back(tip);
4130
4131 treasureCloseUp = new Quad();
4132 treasureCloseUp->position = rightCenter;
4133 treasureCloseUp->alpha = 0;
4134 menuBg->addChild(treasureCloseUp, PM_POINTER);
4135
4136
4137
4138 menuBg->alpha = 0;
4139 }
4140
onNextRecipePage()4141 void Game::onNextRecipePage()
4142 {
4143 game->recipeMenu.goNextPage();
4144 }
4145
onPrevRecipePage()4146 void Game::onPrevRecipePage()
4147 {
4148 game->recipeMenu.goPrevPage();
4149 }
4150
toggleOverrideZoom(bool on)4151 void Game::toggleOverrideZoom(bool on)
4152 {
4153 if (avatar)
4154 {
4155 if (on )
4156 {
4157 if (avatar->isEntityDead())
4158 return;
4159 }
4160 if (!on && avatar->zoomOverriden == true)
4161 {
4162 dsq->globalScale.stop();
4163 avatar->myZoom = dsq->globalScale;
4164 }
4165 avatar->zoomOverriden = on;
4166 }
4167 }
4168
addProgress()4169 void Game::addProgress()
4170 {
4171 if (progressBar)
4172 {
4173 progressBar->progress();
4174 }
4175 }
4176
endProgress()4177 void Game::endProgress()
4178 {
4179 if (progressBar)
4180 {
4181 progressBar->setLife(1);
4182 progressBar->setDecayRate(1.0f/0.5f);
4183 progressBar->fadeAlphaWithLife = 1;
4184 progressBar = 0;
4185 }
4186 }
4187
loadSceneXML(std::string scene)4188 bool Game::loadSceneXML(std::string scene)
4189 {
4190 bgSfxLoop = "";
4191 airSfxLoop = "";
4192 elementTemplatePack = "Main";
4193 entitySaveData.clear();
4194 std::string fn = getSceneFilename(scene);
4195 if (!exists(fn))
4196 {
4197 //errorLog("Could not find [" + fn + "]");
4198 //msg("Could not find map [" + fn + "]");
4199 std::string s = "Could not find map [" + fn + "]";
4200 dsq->screenMessage(s);
4201 return false;
4202 }
4203 XMLDocument doc;
4204 if(readXML(fn, doc) != XML_SUCCESS)
4205 {
4206 dsq->screenMessage("Could not load scene [" + fn + "] - Malformed XML");
4207 return false;
4208 }
4209 if (saveFile)
4210 {
4211 delete saveFile;
4212 saveFile = 0;
4213 }
4214 if (!saveFile)
4215 {
4216 saveFile = new XMLDocument();
4217 }
4218
4219 addProgress();
4220
4221 clearObsRows();
4222 warpAreas.clear();
4223 XMLElement *lensFlare = doc.FirstChildElement("LensFlare");
4224 while (lensFlare)
4225 {
4226 LensFlare *l = new LensFlare;
4227 SimpleIStringStream is(lensFlare->Attribute("tex"));
4228 int w = -1, h=-1;
4229 w = atoi(lensFlare->Attribute("w"));
4230 h = atoi(lensFlare->Attribute("h"));
4231
4232 std::string tex;
4233 while (is >> tex)
4234 {
4235 if (!tex.empty())
4236 l->addFlare(tex, Vector(1,1,1), w, h);
4237 }
4238 SimpleIStringStream is2(lensFlare->Attribute("inc"));
4239 is2 >> l->inc;
4240 l->maxLen = atoi(lensFlare->Attribute("maxLen"));
4241 /*
4242 l->addFlare("flares/flare0", Vector(1,1,0.5));
4243 l->addFlare("flares/flare1", Vector(1,1,1));
4244 l->addFlare("flares/flare2", Vector(0.5,1,1));
4245 l->addFlare("flares/flare2", Vector(1,1,1));
4246 */
4247 l->position = Vector(atoi(lensFlare->Attribute("x")),atoi(lensFlare->Attribute("y")));
4248 addRenderObject(l, LR_LIGHTING);
4249
4250 XMLElement *lSF = saveFile->NewElement("LensFlare");
4251 lSF->SetAttribute("inc", lensFlare->Attribute("inc"));
4252 lSF->SetAttribute("x", lensFlare->Attribute("x"));
4253 lSF->SetAttribute("y", lensFlare->Attribute("y"));
4254 lSF->SetAttribute("tex", lensFlare->Attribute("tex"));
4255 lSF->SetAttribute("w", lensFlare->Attribute("w"));
4256 lSF->SetAttribute("h", lensFlare->Attribute("h"));
4257 lSF->SetAttribute("maxLen", lensFlare->Attribute("maxLen"));
4258 saveFile->InsertEndChild(lSF);
4259
4260 lensFlare = lensFlare->NextSiblingElement("LensFlare");
4261 }
4262 XMLElement *level = doc.FirstChildElement("Level");
4263 if (level)
4264 {
4265 XMLElement *levelSF = saveFile->NewElement("Level");
4266 if (level->Attribute("tileset"))
4267 {
4268 elementTemplatePack = level->Attribute("tileset");
4269 loadElementTemplates(elementTemplatePack);
4270 levelSF->SetAttribute("tileset", elementTemplatePack.c_str());
4271 }
4272 else if (level->Attribute("elementTemplatePack"))
4273 {
4274 elementTemplatePack = level->Attribute("elementTemplatePack");
4275 loadElementTemplates(elementTemplatePack);
4276 levelSF->SetAttribute("tileset", elementTemplatePack.c_str());
4277 }
4278 else
4279 return false;
4280
4281 if (level->Attribute("waterLevel"))
4282 {
4283 useWaterLevel = true;
4284 waterLevel = atoi(level->Attribute("waterLevel"));
4285 saveWaterLevel = atoi(level->Attribute("waterLevel"));
4286 levelSF->SetAttribute("waterLevel", waterLevel.x);
4287 }
4288 if (level->Attribute("worldMapIndex"))
4289 {
4290 worldMapIndex = atoi(level->Attribute("worldMapIndex"));
4291 levelSF->SetAttribute("worldMapIndex", worldMapIndex);
4292 }
4293
4294 if (level->Attribute("bgSfxLoop"))
4295 {
4296 bgSfxLoop = level->Attribute("bgSfxLoop");
4297 levelSF->SetAttribute("bgSfxLoop", bgSfxLoop.c_str());
4298 }
4299 if (level->Attribute("airSfxLoop"))
4300 {
4301 airSfxLoop = level->Attribute("airSfxLoop");
4302 levelSF->SetAttribute("airSfxLoop", airSfxLoop.c_str());
4303 }
4304 if (level->Attribute("bnat"))
4305 {
4306 bNatural = atoi(level->Attribute("bnat"));
4307 levelSF->SetAttribute("bnat", 1);
4308 }
4309 else
4310 {
4311 bNatural = false;
4312 }
4313
4314 /*
4315 if (level->Attribute("darkLayer"))
4316 {
4317 int v = (atoi(level->Attribute("darkLayer")));
4318
4319 levelSF->SetAttribute("darkLayer", v);
4320 }
4321 */
4322 dsq->darkLayer.toggle(true);
4323
4324 if (level->Attribute("bgRepeat"))
4325 {
4326 SimpleIStringStream is(level->Attribute("bgRepeat"));
4327 is >> backgroundImageRepeat;
4328 levelSF->SetAttribute("bgRepeat", level->Attribute("bgRepeat"));
4329 }
4330 if (level->Attribute("cameraConstrained"))
4331 {
4332 SimpleIStringStream is(level->Attribute("cameraConstrained"));
4333 is >> cameraConstrained;
4334 levelSF->SetAttribute("cameraConstrained", cameraConstrained);
4335 std::ostringstream os;
4336 os << "cameraConstrained: " << cameraConstrained;
4337 debugLog(os.str());
4338 }
4339 if (level->Attribute("maxZoom"))
4340 {
4341 maxZoom = atof(level->Attribute("maxZoom"));
4342 std::ostringstream os;
4343 os << maxZoom;
4344 levelSF->SetAttribute("maxZoom", os.str().c_str());
4345 }
4346 if (level->Attribute("natureForm"))
4347 {
4348 sceneNatureForm = level->Attribute("natureForm");
4349 levelSF->SetAttribute("natureForm", sceneNatureForm.c_str());
4350 }
4351 if (level->Attribute("bg"))
4352 {
4353 std::string tex = std::string(level->Attribute("bg"));
4354 if (!tex.empty())
4355 {
4356 /*
4357 if (tex.find('.') == std::string::npos)
4358 bg->setTexture(tex+"");
4359 else
4360 bg->setTexture(tex);
4361 */
4362
4363 bg->setTexture(tex);
4364 bg->setWidthHeight(900,600);
4365 levelSF->SetAttribute("bg", tex.c_str());
4366 }
4367 else
4368 {
4369 bg->alpha = 0;
4370 }
4371 }
4372 else
4373 {
4374 bg->alpha = 0;
4375 //grad->alpha =0;
4376 }
4377 gradTop = gradBtm = Vector(0,0,0);
4378 if (level->Attribute("gradient"))
4379 {
4380 if (level->Attribute("gradTop"))
4381 {
4382 SimpleIStringStream is(level->Attribute("gradTop"));
4383 is >> gradTop.x >> gradTop.y >> gradTop.z;
4384 levelSF->SetAttribute("gradTop", level->Attribute("gradTop"));
4385 }
4386 if (level->Attribute("gradBtm"))
4387 {
4388 SimpleIStringStream is(level->Attribute("gradBtm"));
4389 is >> gradBtm.x >> gradBtm.y >> gradBtm.z;
4390 levelSF->SetAttribute("gradBtm", level->Attribute("gradBtm"));
4391 }
4392 createGradient();
4393 levelSF->SetAttribute("gradient", 1);
4394 }
4395
4396 if (level->Attribute("parallax"))
4397 {
4398 SimpleIStringStream is(level->Attribute("parallax"));
4399 float x,y,z,r,g,b;
4400 is >> x >> y >> z >> r >> g >> b;
4401 RenderObjectLayer *l = 0;
4402 l = &dsq->renderObjectLayers[LR_ELEMENTS10];
4403 l->followCamera = x;
4404 l = &dsq->renderObjectLayers[LR_ELEMENTS11];
4405 l->followCamera = y;
4406 l = &dsq->renderObjectLayers[LR_ENTITIES_MINUS4_PLACEHOLDER];
4407 l->followCamera = y;
4408 l = &dsq->renderObjectLayers[LR_ENTITIES_MINUS4];
4409 l->followCamera = y;
4410 l = &dsq->renderObjectLayers[LR_ELEMENTS12];
4411 l->followCamera = z;
4412 l = &dsq->renderObjectLayers[LR_ELEMENTS14];
4413 l->followCamera = r;
4414 l = &dsq->renderObjectLayers[LR_ELEMENTS15];
4415 l->followCamera = g;
4416 l = &dsq->renderObjectLayers[LR_ELEMENTS16];
4417 l->followCamera = b;
4418 levelSF->SetAttribute("parallax", level->Attribute("parallax"));
4419 }
4420
4421 if (level->Attribute("parallaxLock"))
4422 {
4423 int x, y, z, r, g, b;
4424 SimpleIStringStream is(level->Attribute("parallaxLock"));
4425 is >> x >> y >> z >> r >> g >> b;
4426
4427 RenderObjectLayer *l = 0;
4428 l = &dsq->renderObjectLayers[LR_ELEMENTS10];
4429 l->followCameraLock = x;
4430 l = &dsq->renderObjectLayers[LR_ELEMENTS11];
4431 l->followCameraLock = y;
4432 l = &dsq->renderObjectLayers[LR_ELEMENTS12];
4433 l->followCameraLock = z;
4434 l = &dsq->renderObjectLayers[LR_ELEMENTS14];
4435 l->followCameraLock = r;
4436 l = &dsq->renderObjectLayers[LR_ELEMENTS15];
4437 l->followCameraLock = g;
4438 l = &dsq->renderObjectLayers[LR_ELEMENTS16];
4439 l->followCameraLock = b;
4440
4441 levelSF->SetAttribute("parallaxLock", level->Attribute("parallaxLock"));
4442 }
4443
4444 if (level->Attribute("bg2"))
4445 {
4446
4447 std::string tex = std::string(level->Attribute("bg2"));
4448 if (!tex.empty())
4449 {
4450 /*
4451 if (tex.find('.') == std::string::npos)
4452 bg2->setTexture(tex+"");
4453 else
4454 bg2->setTexture(tex);
4455 */
4456 bg2->setTexture(tex);
4457 bg2->setWidthHeight(900,600);
4458 levelSF->SetAttribute("bg2", tex.c_str());
4459
4460 }
4461 else
4462 bg2->alpha = 0;
4463 //createGradient();
4464
4465 bg2->alpha = 0;
4466 bg->alpha = 0;
4467 }
4468 else
4469 {
4470 bg2->alpha = 0;
4471 //grad->alpha =0;
4472 }
4473
4474 if (level->Attribute("backdrop"))
4475 {
4476 std::string backdrop = level->Attribute("backdrop");
4477 backdropQuad = new Quad;
4478 backdropQuad->setTexture(backdrop);
4479 backdropQuad->blendEnabled = false;
4480
4481 if (level->Attribute("bd-x") && level->Attribute("bd-y"))
4482 {
4483 int x = atoi(level->Attribute("bd-x"));
4484 int y = atoi(level->Attribute("bd-y"));
4485 backdropQuad->position = Vector(x,y);
4486 levelSF->SetAttribute("bd-x", x);
4487 levelSF->SetAttribute("bd-y", y);
4488 }
4489 if (level->Attribute("bd-w") && level->Attribute("bd-h"))
4490 {
4491 int w = atoi(level->Attribute("bd-w"));
4492 int h = atoi(level->Attribute("bd-h"));
4493 backdropQuad->setWidthHeight(w, h);
4494 levelSF->SetAttribute("bd-w", w);
4495 levelSF->SetAttribute("bd-h", h);
4496 }
4497 backdropQuad->toggleCull(false);
4498 //backdropQuad->followCamera = 1;
4499 addRenderObject(backdropQuad, LR_SCENEBACKGROUNDIMAGE);
4500
4501 // upper left justify
4502 backdropQuad->offset =
4503 Vector((backdropQuad->getWidth()*backdropQuad->scale.x)/2.0f,
4504 (backdropQuad->getHeight()*backdropQuad->scale.y)/2.0f);
4505 // save
4506 levelSF->SetAttribute("backdrop", backdrop.c_str());
4507 //backdrop="cavebg" bd-w="2400" bd-h="2400"
4508 }
4509 musicToPlay = "";
4510 if (level->Attribute("music"))
4511 {
4512 setMusicToPlay(level->Attribute("music"));
4513 saveMusic = level->Attribute("music");
4514 levelSF->SetAttribute("music", level->Attribute("music"));
4515 /*
4516 // if using SDL_Mixer
4517 if (!core->sound->isPlayingMusic(musicToPlay))
4518 {
4519 core->sound->fadeMusic(SFT_OUT, 1);
4520 }
4521 */
4522 }
4523 if (level->Attribute("sceneColor"))
4524 {
4525 SimpleIStringStream in(level->Attribute("sceneColor"));
4526 in >> sceneColor.x >> sceneColor.y >> sceneColor.z;
4527 levelSF->SetAttribute("sceneColor", level->Attribute("sceneColor"));
4528 }
4529
4530 saveFile->InsertEndChild(levelSF);
4531 }
4532 else
4533 return false;
4534
4535 XMLElement *obs = doc.FirstChildElement("Obs");
4536 if (obs)
4537 {
4538 int tx, ty, len;
4539 SimpleIStringStream is(obs->Attribute("d"));
4540 while (is >> tx)
4541 {
4542 is >> ty >> len;
4543 addObsRow(tx, ty, len);
4544 }
4545 addProgress();
4546 }
4547
4548 XMLElement *pathXml = doc.FirstChildElement("Path");
4549 while (pathXml)
4550 {
4551 Path *path = new Path;
4552 path->name = pathXml->Attribute("name");
4553 stringToLower(path->name);
4554 /*
4555 if (pathXml->Attribute("active"))
4556 {
4557 path.active = atoi(pathXml->Attribute("active"));
4558 }
4559 */
4560 XMLElement *nodeXml = pathXml->FirstChildElement("Node");
4561 while (nodeXml)
4562 {
4563 PathNode node;
4564 SimpleIStringStream is(nodeXml->Attribute("pos"));
4565 is >> node.position.x >> node.position.y;
4566
4567 if (nodeXml->Attribute("ms"))
4568 {
4569 node.maxSpeed = atoi(nodeXml->Attribute("ms"));
4570 }
4571
4572 if (nodeXml->Attribute("rect"))
4573 {
4574 SimpleIStringStream is(nodeXml->Attribute("rect"));
4575 int w,h;
4576 is >> w >> h;
4577 path->rect.setWidth(w);
4578 path->rect.setHeight(h);
4579 }
4580
4581 if (nodeXml->Attribute("shape"))
4582 {
4583 path->pathShape = (PathShape)atoi(nodeXml->Attribute("shape"));
4584 }
4585
4586 path->nodes.push_back(node);
4587 nodeXml = nodeXml->NextSiblingElement("Node");
4588 }
4589 path->refreshScript();
4590 addPath(path);
4591 addProgress();
4592 pathXml = pathXml->NextSiblingElement("Path");
4593 }
4594
4595 XMLElement *quad = doc.FirstChildElement("Quad");
4596 while (quad)
4597 {
4598 XMLElement *qSF = saveFile->NewElement("Quad");
4599 int x=0, y=0, z=0;
4600 int w=0,h=0;
4601 bool cull=true;
4602 bool solid = false;
4603 std::string justify;
4604 std::string tex;
4605 qSF->SetAttribute("x", x = atoi(quad->Attribute("x")));
4606 qSF->SetAttribute("y", y = atoi(quad->Attribute("y")));
4607 //qSF->SetAttribute("z", z = atoi(quad->Attribute("z")));
4608 qSF->SetAttribute("w", w = atoi(quad->Attribute("w")));
4609 qSF->SetAttribute("h", h = atoi(quad->Attribute("h")));
4610 qSF->SetAttribute("tex", (tex = (quad->Attribute("tex"))).c_str());
4611 qSF->SetAttribute("cull", cull = atoi(quad->Attribute("cull")));
4612 qSF->SetAttribute("justify", (justify = (quad->Attribute("justify"))).c_str());
4613
4614 if (quad->Attribute("solid"))
4615 qSF->SetAttribute("solid", solid = atoi(quad->Attribute("solid")));
4616
4617 Quad *q = new Quad;
4618 q->position = Vector(x,y,z);
4619 /*
4620 if (solid)
4621 Texture::pngLoadHaloFix = false;
4622 */
4623 q->setTexture(tex);
4624 /*
4625 if (solid)
4626 Texture::pngLoadHaloFix = true;
4627 */
4628 q->toggleCull(cull);
4629 q->setWidthHeight(w, h);
4630
4631 if (justify == "upperLeft")
4632 {
4633 q->offset = Vector((q->getWidth()*q->scale.x)/2.0f, (q->getHeight()*q->scale.y)/2.0f);
4634 }
4635 addRenderObject(q, LR_BACKGROUND);
4636
4637 saveFile->InsertEndChild(qSF);
4638
4639 quad = quad->NextSiblingElement("Quad");
4640 }
4641
4642 XMLElement *floater = doc.FirstChildElement("Floater");
4643 while(floater)
4644 {
4645 XMLElement *nSF = doc.NewElement("Floater");
4646 if (!floater->Attribute("boxW") || !floater->Attribute("boxH"))
4647 {
4648 errorLog ("no boxW/boxH");
4649 break;
4650 }
4651 int boxW, boxH, x, y, fx, fy;
4652 nSF->SetAttribute("boxW", boxW = atoi(floater->Attribute("boxW")));
4653 nSF->SetAttribute("boxH", boxH = atoi(floater->Attribute("boxH")));
4654 nSF->SetAttribute("tex", floater->Attribute("tex"));
4655 nSF->SetAttribute("x", x = atoi(floater->Attribute("x")));
4656 nSF->SetAttribute("y", y = atoi(floater->Attribute("y")));
4657 nSF->SetAttribute("fx", fx = atoi(floater->Attribute("fx")));
4658 nSF->SetAttribute("fy", fy = atoi(floater->Attribute("fy")));
4659
4660 /*
4661 Floater *f = new Floater(Vector(x,y), Vector(fx, fy), boxW, boxH, tex);
4662 {
4663 }
4664 addRenderObject(f, LR_BACKGROUND);
4665 saveFile->InsertEndChild(nSF);
4666 */
4667 floater = floater->NextSiblingElement("Floater");
4668
4669 }
4670
4671 /*
4672 XMLElement *breakable = doc.FirstChildElement("Breakable");
4673 while(breakable)
4674 {
4675 XMLElement *nSF = doc.NewElement("Breakable");
4676 if (!breakable->Attribute("boxW") || !breakable->Attribute("boxH"))
4677 {
4678 errorLog ("Breakable error.. no boxW/boxH");
4679 break;
4680 }
4681 int boxW, boxH;
4682 std::string tex;
4683 nSF->SetAttribute("boxW", boxW = atoi(breakable->Attribute("boxW")));
4684 nSF->SetAttribute("boxH", boxH = atoi(breakable->Attribute("boxH")));
4685 tex = breakable->Attribute("tex");
4686 nSF->SetAttribute("tex", tex);
4687 Breakable *n = new Breakable(boxW, boxH, tex);
4688 {
4689 nSF->SetAttribute("x", n->position.x = atoi(breakable->Attribute("x")));
4690 nSF->SetAttribute("y", n->position.y = atoi(breakable->Attribute("y")));
4691 int w=0, h=0;
4692 if (breakable->Attribute("w"))
4693 nSF->SetAttribute("w", w = atoi(breakable->Attribute("w")));
4694 if (breakable->Attribute("h"))
4695 nSF->SetAttribute("h", h= atoi(breakable->Attribute("h")));
4696 if (w != 0 && h != 0)
4697 {
4698 n->setWidthHeight(w, h);
4699 }
4700 }
4701 addRenderObject(n, LR_BACKGROUND);
4702 saveFile->InsertEndChild(nSF);
4703 breakable = breakable->NextSiblingElement("Breakable");
4704 }
4705 */
4706
4707 XMLElement *warpArea = doc.FirstChildElement("WarpArea");
4708 while(warpArea)
4709 {
4710 XMLElement *waSF = doc.NewElement("WarpArea");
4711 WarpArea a;
4712 waSF->SetAttribute("x", a.position.x = atoi(warpArea->Attribute("x")));
4713 waSF->SetAttribute("y", a.position.y = atoi(warpArea->Attribute("y")));
4714 if (warpArea->Attribute("radius"))
4715 waSF->SetAttribute("radius", a.radius = atoi(warpArea->Attribute("radius")));
4716 bool isRect = false;
4717 if (warpArea->Attribute("w"))
4718 {
4719 isRect = true;
4720 waSF->SetAttribute("w", a.w = atoi(warpArea->Attribute("w")));
4721 waSF->SetAttribute("h", a.h = atoi(warpArea->Attribute("h")));
4722 }
4723 if (warpArea->Attribute("g"))
4724 {
4725 waSF->SetAttribute("g", a.generated = atoi(warpArea->Attribute("g")));
4726 }
4727 std::string sceneString = warpArea->Attribute("scene");
4728 waSF->SetAttribute("scene", sceneString.c_str());
4729 /*
4730 waSF->SetAttribute("ax", a.avatarPosition.x = atoi(warpArea->Attribute("ax")));
4731 waSF->SetAttribute("ay", a.avatarPosition.y = atoi(warpArea->Attribute("ay")));
4732 */
4733
4734 SimpleIStringStream is(sceneString);
4735 std::string sceneName, warpAreaType, side;
4736 is >> sceneName >> warpAreaType >> a.spawnOffset.x >> a.spawnOffset.y;
4737 a.spawnOffset.normalize2D();
4738 a.sceneName = sceneName;
4739 a.warpAreaType = warpAreaType;
4740 //a.side = side;
4741 // saveFile->InsertEndChild(waSF);
4742
4743 bool add = true;
4744 std::string flagCheck;
4745 if (warpArea->Attribute("flagCheck"))
4746 {
4747 flagCheck = warpArea->Attribute("flagCheck");
4748 add = doFlagCheck(flagCheck);
4749 }
4750 if (add)
4751 warpAreas.push_back(a);
4752
4753 if (a.generated)
4754 {
4755 setWarpAreaSceneName(a);
4756 }
4757
4758 warpArea = warpArea->NextSiblingElement("WarpArea");
4759 }
4760
4761 XMLElement *schoolFish = doc.FirstChildElement("SchoolFish");
4762 while(schoolFish)
4763 {
4764 int num = atoi(schoolFish->Attribute("num"));
4765 int x, y;
4766 int id;
4767 x = atoi(schoolFish->Attribute("x"));
4768 y = atoi(schoolFish->Attribute("y"));
4769 id = atoi(schoolFish->Attribute("id"));
4770 std::string gfx, texture="flock-0001";
4771 if (schoolFish->Attribute("gfx"))
4772 {
4773 gfx = schoolFish->Attribute("gfx");
4774 texture = gfx;
4775 /*
4776 std::ostringstream os;
4777 os << "flock-" << gfx << "";
4778 texture = os.str();
4779 */
4780 }
4781 int layer = 0;
4782 if (schoolFish->Attribute("layer"))
4783 {
4784 layer = atoi(schoolFish->Attribute("layer"));
4785 }
4786
4787 float size = 1;
4788 if (schoolFish->Attribute("size"))
4789 {
4790 SimpleIStringStream is(schoolFish->Attribute("size"));
4791 is >> size;
4792 }
4793
4794 int maxSpeed = 0;
4795 if (schoolFish->Attribute("maxSpeed"))
4796 maxSpeed = atoi(schoolFish->Attribute("maxSpeed"));
4797
4798 int range = 0;
4799 if (schoolFish->Attribute("range"))
4800 range = atoi(schoolFish->Attribute("range"));
4801
4802 for (int i = 0; i < num; i++)
4803 {
4804 SchoolFish *s = new SchoolFish(texture);
4805 {
4806 s->position = Vector(x+i*5,y+i*5);
4807 s->startPos = s->position;
4808 s->addToFlock(id);
4809 if (range != 0)
4810 s->range = range;
4811 if (maxSpeed != 0)
4812 s->setMaxSpeed(maxSpeed);
4813
4814 std::ostringstream os;
4815 os << "adding schoolfish (" << s->position.x << ", " << s->position.y << ")";
4816 debugLog(os.str());
4817 }
4818 if (layer == -3)
4819 {
4820 addRenderObject(s, LR_ELEMENTS11);
4821 }
4822 else
4823 {
4824 if (chance(50))
4825 addRenderObject(s, LR_ENTITIES2);
4826 else
4827 addRenderObject(s, LR_ENTITIES);
4828 }
4829
4830 /*if (layer == 1)
4831 {
4832 addRenderObject(s, LR_ENTITIES);
4833 }
4834 else
4835 {
4836 // school fish layer hack
4837 // because we want all fish on top dammit
4838 //addRenderObject(s, LR_ENTITIES2);
4839
4840 // or... not?
4841 //hrm.. why not?
4842 if (chance(50))
4843 addRenderObject(s, LR_ENTITIES2);
4844 else
4845 addRenderObject(s, LR_ENTITIES);
4846 //s->setOverrideRenderPass(4);
4847 }
4848 */
4849 s->applyLayer(layer);
4850
4851 s->scale *= size;
4852 //s->update(0.033);
4853
4854 }
4855
4856 schoolFish = schoolFish->NextSiblingElement("SchoolFish");
4857
4858 XMLElement *newSF = saveFile->NewElement("SchoolFish");
4859 newSF->SetAttribute("x", x);
4860 newSF->SetAttribute("y", y);
4861 newSF->SetAttribute("id", id);
4862 newSF->SetAttribute("num", num);
4863
4864 if (range != 0)
4865 newSF->SetAttribute("range", range);
4866 if (maxSpeed != 0)
4867 newSF->SetAttribute("maxSpeed", maxSpeed);
4868 if (layer != 0)
4869 newSF->SetAttribute("layer", layer);
4870 if (!gfx.empty())
4871 newSF->SetAttribute("gfx", gfx.c_str());
4872 if (size != 1)
4873 newSF->SetAttribute("size", size);
4874
4875 saveFile->InsertEndChild(newSF);
4876 }
4877 /*
4878 XMLElement *boxElement = doc.FirstChildElement("BoxElement");
4879 while (boxElement)
4880 {
4881 BoxElement *b = new BoxElement(atoi(boxElement->Attribute("w")), atoi(boxElement->Attribute("h")));
4882 b->position = Vector(atoi(boxElement->Attribute("x")), atoi(boxElement->Attribute("y")));
4883 addRenderObject(b, LR_BLACKGROUND);
4884 b->position.z = boxElementZ;
4885 dsq->addElement(b);
4886 boxElement = boxElement->NextSiblingElement("BoxElement");
4887 }
4888 */
4889 std::vector<Element*> loadedElements;
4890 loadedElements.reserve(200);
4891 XMLElement *simpleElements = doc.FirstChildElement("SE");
4892 while (simpleElements)
4893 {
4894 int idx, x, y, rot;
4895 float sz,sz2;
4896 loadedElements.clear();
4897 if (simpleElements->Attribute("d"))
4898 {
4899 SimpleIStringStream is(simpleElements->Attribute("d"));
4900 while (is >> idx)
4901 {
4902 is >> x >> y >> rot;
4903 Element *e = createElement(idx, Vector(x,y), 4);
4904 e->rotation.z = rot;
4905 loadedElements.push_back(e);
4906 }
4907 }
4908 if (simpleElements->Attribute("e"))
4909 {
4910 SimpleIStringStream is2(simpleElements->Attribute("e"));
4911 int l = atoi(simpleElements->Attribute("l"));
4912 while(is2 >> idx)
4913 {
4914 is2 >> x >> y >> rot;
4915 Element *e = createElement(idx, Vector(x,y), l);
4916 e->rotation.z = rot;
4917 loadedElements.push_back(e);
4918 }
4919 }
4920 if (simpleElements->Attribute("f"))
4921 {
4922 SimpleIStringStream is2(simpleElements->Attribute("f"));
4923 int l = atoi(simpleElements->Attribute("l"));
4924 while(is2 >> idx)
4925 {
4926 is2 >> x >> y >> rot >> sz;
4927 Element *e = createElement(idx, Vector(x,y), l);
4928 e->scale = Vector(sz,sz);
4929 e->rotation.z = rot;
4930 loadedElements.push_back(e);
4931 }
4932 }
4933 if (simpleElements->Attribute("g"))
4934 {
4935 SimpleIStringStream is2(simpleElements->Attribute("g"));
4936 int l = atoi(simpleElements->Attribute("l"));
4937 while(is2 >> idx)
4938 {
4939 int fh, fv;
4940 is2 >> x >> y >> rot >> sz >> fh >> fv;
4941 Element *e = createElement(idx, Vector(x,y), l);
4942 if (fh)
4943 e->flipHorizontal();
4944 if (fv)
4945 e->flipVertical();
4946 e->scale = Vector(sz,sz);
4947 e->rotation.z = rot;
4948 loadedElements.push_back(e);
4949 }
4950 }
4951 if (simpleElements->Attribute("h"))
4952 {
4953 SimpleIStringStream is2(simpleElements->Attribute("h"));
4954 int l = atoi(simpleElements->Attribute("l"));
4955 while(is2 >> idx)
4956 {
4957 int fh, fv;
4958 int flags;
4959 is2 >> x >> y >> rot >> sz >> fh >> fv >> flags;
4960 Element *e = createElement(idx, Vector(x,y), l);
4961 e->elementFlag = (ElementFlag)flags;
4962 if (e->elementFlag >= EF_MAX || e->elementFlag < EF_NONE)
4963 e->elementFlag = EF_NONE;
4964 if (fh)
4965 e->flipHorizontal();
4966 if (fv)
4967 e->flipVertical();
4968 e->scale = Vector(sz,sz);
4969 e->rotation.z = rot;
4970 loadedElements.push_back(e);
4971 }
4972 }
4973 if (simpleElements->Attribute("i"))
4974 {
4975 SimpleIStringStream is2(simpleElements->Attribute("i"));
4976 int l = atoi(simpleElements->Attribute("l"));
4977 while(is2 >> idx)
4978 {
4979 int fh, fv;
4980 int flags;
4981 int efxIdx;
4982 is2 >> x >> y >> rot >> sz >> fh >> fv >> flags >> efxIdx;
4983 if (sz < MIN_SIZE)
4984 sz = MIN_SIZE;
4985 Element *e = createElement(idx, Vector(x,y), l);
4986 e->elementFlag = (ElementFlag)flags;
4987 if (fh)
4988 e->flipHorizontal();
4989 if (fv)
4990 e->flipVertical();
4991
4992 e->scale = Vector(sz,sz);
4993 e->rotation.z = rot;
4994 e->setElementEffectByIndex(efxIdx);
4995 loadedElements.push_back(e);
4996 }
4997 }
4998 if (simpleElements->Attribute("j"))
4999 {
5000 SimpleIStringStream is2(simpleElements->Attribute("j"));
5001 int l = atoi(simpleElements->Attribute("l"));
5002 while(is2 >> idx)
5003 {
5004 int fh, fv;
5005 int flags;
5006 int efxIdx;
5007 int repeat;
5008 is2 >> x >> y >> rot >> sz >> fh >> fv >> flags >> efxIdx >> repeat;
5009 if (sz < MIN_SIZE)
5010 sz = MIN_SIZE;
5011 Element *e = createElement(idx, Vector(x,y), l);
5012 e->elementFlag = (ElementFlag)flags;
5013 if (fh)
5014 e->flipHorizontal();
5015 if (fv)
5016 e->flipVertical();
5017
5018 e->scale = Vector(sz,sz);
5019 e->rotation.z = rot;
5020 e->setElementEffectByIndex(efxIdx);
5021 if (repeat)
5022 e->repeatTextureToFill(true);
5023 loadedElements.push_back(e);
5024 }
5025 }
5026 if (simpleElements->Attribute("k"))
5027 {
5028 SimpleIStringStream is2(simpleElements->Attribute("k"));
5029 int l = atoi(simpleElements->Attribute("l"));
5030 int c = 0;
5031 while(is2 >> idx)
5032 {
5033 int fh, fv;
5034 int flags;
5035 int efxIdx;
5036 int repeat;
5037 is2 >> x >> y >> rot >> sz >> sz2 >> fh >> fv >> flags >> efxIdx >> repeat;
5038 if (sz < MIN_SIZE)
5039 sz = MIN_SIZE;
5040 if (sz2 < MIN_SIZE)
5041 sz2 = MIN_SIZE;
5042 Element *e = createElement(idx, Vector(x,y), l);
5043 e->elementFlag = (ElementFlag)flags;
5044 if (fh)
5045 e->flipHorizontal();
5046 if (fv)
5047 e->flipVertical();
5048
5049 e->scale = Vector(sz,sz2);
5050 e->rotation.z = rot;
5051 e->setElementEffectByIndex(efxIdx);
5052 if (repeat)
5053 e->repeatTextureToFill(true);
5054
5055 c++;
5056 if (c> 100)
5057 {
5058 c=0;
5059 addProgress();
5060 }
5061
5062 loadedElements.push_back(e);
5063 }
5064 }
5065 if (simpleElements->Attribute("repeatScale"))
5066 {
5067 SimpleIStringStream is2(simpleElements->Attribute("repeatScale"));
5068 for(size_t i = 0; i < loadedElements.size(); ++i)
5069 {
5070 Element *e = loadedElements[i];
5071 if(e->isRepeatingTextureToFill())
5072 {
5073 float repeatScaleX = 1, repeatScaleY = 1;
5074 if(!(is2 >> repeatScaleX >> repeatScaleY))
5075 break;
5076 e->repeatToFillScale.x = repeatScaleX;
5077 e->repeatToFillScale.y = repeatScaleY;
5078 e->refreshRepeatTextureToFill();
5079 }
5080 }
5081 }
5082 simpleElements = simpleElements->NextSiblingElement("SE");
5083 }
5084
5085 XMLElement *element = doc.FirstChildElement("Element");
5086 while (element)
5087 {
5088 if (element->Attribute("idx"))
5089 {
5090 int x = atoi(element->Attribute("x"));
5091 int y = atoi(element->Attribute("y"));
5092 int idx = atoi(element->Attribute("idx"));
5093 int layer=LR_ELEMENTS5;
5094 float rot =0;
5095 bool flipH = false, flipV = false;
5096 if (element->Attribute("flipH"))
5097 flipH = atoi(element->Attribute("flipH"));
5098 if (element->Attribute("flipV"))
5099 flipV = atoi(element->Attribute("flipV"));
5100
5101 if (element->Attribute("rot"))
5102 rot = atof(element->Attribute("rot"));
5103
5104 if (element->Attribute("lyr"))
5105 layer = atoi(element->Attribute("lyr"));
5106
5107
5108 if (idx != -1)
5109 {
5110 Element *e = createElement(idx, Vector(x,y), layer);
5111 e->rotation.z = rot;
5112 if (flipH)
5113 e->flipHorizontal();
5114 if (flipV)
5115 e->flipVertical();
5116
5117 if (element->Attribute("sz"))
5118 {
5119 SimpleIStringStream is(element->Attribute("sz"));
5120 is >> e->scale.x >> e->scale.y;
5121 }
5122 }
5123
5124
5125 }
5126 element = element->NextSiblingElement("Element");
5127 }
5128
5129 this->reconstructGrid(true);
5130
5131 /*
5132 XMLElement *enemyNode = doc.FirstChildElement("Enemy");
5133 while(enemyNode)
5134 {
5135 Vector pos;
5136 pos.x = atoi(enemyNode->Attribute("x"));
5137 pos.y = atoi(enemyNode->Attribute("y"));
5138
5139 std::string type = enemyNode->Attribute("type");
5140
5141 std::string flagCheck;
5142 if (enemyNode->Attribute("flagCheck"))
5143 {
5144 flagCheck = enemyNode->Attribute("flagCheck");
5145 }
5146 if (doFlagCheck(flagCheck))
5147 Entity *e = createEnemy(type, pos, true, enemyNode, flagCheck, -1);
5148
5149 enemyNode = enemyNode->NextSiblingElement("Enemy");
5150 }
5151 */
5152 XMLElement *entitiesNode = doc.FirstChildElement("Entities");
5153 while(entitiesNode)
5154 {
5155 if (entitiesNode->Attribute("j"))
5156 {
5157 SimpleIStringStream is(entitiesNode->Attribute("j"));
5158 int idx, x, y, rot, groupID, id;
5159 std::string name;
5160 while (is >> idx)
5161 {
5162 name="";
5163 if (idx == -1)
5164 is >> name;
5165 is >> x >> y >> rot >> groupID >> id;
5166
5167 if (!name.empty())
5168 dsq->game->createEntity(name, id, Vector(x,y), rot, true, "", ET_ENEMY);
5169 else
5170 dsq->game->createEntity(idx, id, Vector(x,y), rot, true, "", ET_ENEMY);
5171 }
5172 }
5173 entitiesNode = entitiesNode->NextSiblingElement("Entities");
5174 }
5175 //assignEntitiesUniqueIDs();
5176 //initEntities();
5177 FOR_ENTITIES(i)
5178 {
5179 Entity *e = *i;
5180 e->onSceneFlipped();
5181 }
5182 this->reconstructGrid(true);
5183 rebuildElementUpdateList();
5184 setElementLayerFlags();
5185
5186 // HACK: Don't try to optimize the barrier layer in Mithalas Cathedral
5187 // since elements are turned off dynamically.
5188 if (nocasecmp(scene, "cathedral02") == 0)
5189 dsq->getRenderObjectLayer(LR_ELEMENTS3)->setOptimizeStatic(false);
5190
5191 findMaxCameraValues();
5192
5193 endProgress();
5194
5195 return true;
5196 }
5197
setMusicToPlay(const std::string & m)5198 void Game::setMusicToPlay(const std::string &m)
5199 {
5200 musicToPlay = m;
5201 stringToLower(musicToPlay);
5202 }
5203
findMaxCameraValues()5204 void Game::findMaxCameraValues()
5205 {
5206 cameraMin.x = 20;
5207 cameraMin.y = 20;
5208 cameraMax.x = -1;
5209 cameraMax.y = -1;
5210 int i = 0;
5211 for (i = 0; i < obsRows.size(); i++)
5212 {
5213 ObsRow *r = &obsRows[i];
5214 TileVector t(r->tx + r->len, r->ty);
5215 Vector v = t.worldVector();
5216 if (v.x > cameraMax.x)
5217 {
5218 cameraMax.x = v.x;
5219 }
5220 if (v.y > cameraMax.y)
5221 {
5222 cameraMax.y = v.y;
5223 }
5224 }
5225 /*
5226 for (i = 0; i < dsq->getNumElements(); i++)
5227 {
5228 Element *e = dsq->getElement(i);
5229 if (e->position.x > cameraMax.x)
5230 cameraMax.x = e->position.x;
5231 if (e->position.y > cameraMax.y)
5232 cameraMax.y = e->position.y;
5233 }
5234 */
5235 if (backdropQuad)
5236 {
5237 if (backdropQuad->getWidth() > cameraMax.x)
5238 {
5239 cameraMax.x = backdropQuad->getWidth();
5240 }
5241 if (backdropQuad->getHeight() > cameraMax.y)
5242 {
5243 cameraMax.y = backdropQuad->getHeight();
5244 }
5245 }
5246 }
5247
setWarpAreaSceneName(WarpArea & warpArea)5248 void Game::setWarpAreaSceneName(WarpArea &warpArea)
5249 {
5250 InStream in("data/warpAreas.txt");
5251 std::string color, area1, dir1, area2, dir2;
5252 std::string line;
5253 while (std::getline(in, line))
5254 {
5255
5256 std::istringstream is(line);
5257 is >> color >> area1 >> dir1 >> area2 >> dir2;
5258 /*
5259 errorLog (color + " : " + area1 + " : " + dir1 + " : " + area2 + " : " + dir2);
5260 */
5261 if (area2 == dsq->game->sceneName && warpArea.warpAreaType == color)
5262 {
5263 area2 = area1;
5264 dir2 = dir1;
5265 area1 = dsq->game->sceneName;
5266 }
5267 if (area1 == dsq->game->sceneName && warpArea.warpAreaType == color)
5268 {
5269 if (dir2=="Left")
5270 warpArea.spawnOffset = Vector(-1,0);
5271 else if (dir2=="Right")
5272 warpArea.spawnOffset = Vector(1,0);
5273 else if (dir2=="Up")
5274 warpArea.spawnOffset = Vector(0,-1);
5275 else if (dir2=="Down")
5276 warpArea.spawnOffset = Vector(0,1);
5277 warpArea.sceneName = area2;
5278 break;
5279 }
5280 }
5281 if (warpArea.sceneName.empty())
5282 {
5283 errorLog(warpArea.warpAreaType + " WarpArea for " + dsq->game->sceneName + " not found");
5284 }
5285 }
5286
loadScene(std::string scene)5287 bool Game::loadScene(std::string scene)
5288 {
5289 stringToLower(scene);
5290
5291 sceneName = scene;
5292 if (scene.empty())
5293 {
5294 return false;
5295 }
5296
5297 #ifdef AQUARIA_DEMO
5298 int i = 0;
5299 for (; i < allowedMaps.size(); i++)
5300 {
5301 if (allowedMaps[i] == scene)
5302 break;
5303 }
5304 if (i == allowedMaps.size())
5305 {
5306 exit_error("Demo version refuses to load this map, sorry.");
5307 }
5308 #endif
5309
5310
5311 loadingScene = true;
5312 bool ret = loadSceneXML(scene);
5313 loadingScene = false;
5314
5315 return ret;
5316
5317 /*
5318 std::string fn = ("data/maps/"+scene+".xml");
5319 if (!exists(fn))
5320 {
5321 loadSceneDAT(scene);
5322 return;
5323 }
5324 loadSceneXML(scene);
5325 */
5326
5327
5328 /*
5329
5330 */
5331 }
5332
saveScene(std::string scene)5333 bool Game::saveScene(std::string scene)
5334 {
5335 if (!this->saveFile)
5336 return false;
5337
5338 std::string fn = getSceneFilename(scene);
5339
5340 XMLDocument saveFile;
5341
5342 // hackish: Deep-clone XML doc
5343 {
5344 XMLPrinter printer;
5345 this->saveFile->Print(&printer);
5346
5347 XMLError xmlerr = saveFile.Parse(printer.CStr(), printer.CStrSize());
5348 if(xmlerr != XML_SUCCESS)
5349 {
5350 std::ostringstream os;
5351 os << "Game::saveScene(): Whoops? Deep cloning level XML failed: Error " << xmlerr;
5352 errorLog(os.str());
5353 }
5354 }
5355
5356 XMLElement *level = saveFile.FirstChildElement("Level");
5357 if(!level)
5358 {
5359 level = saveFile.NewElement("Level");
5360 saveFile.InsertFirstChild(level);
5361 }
5362
5363 if (level)
5364 {
5365 level->SetAttribute("waterLevel", dsq->game->saveWaterLevel);
5366
5367 if (grad)
5368 {
5369 level->SetAttribute("gradient", 1);
5370
5371 std::ostringstream os;
5372 os << gradTop.x << " " << gradTop.y << " " << gradTop.z;
5373 level->SetAttribute("gradTop", os.str().c_str());
5374
5375 std::ostringstream os2;
5376 os2 << gradBtm.x << " " << gradBtm.y << " " << gradBtm.z;
5377 level->SetAttribute("gradBtm", os2.str().c_str());
5378
5379 }
5380
5381 if (!saveMusic.empty())
5382 {
5383 level->SetAttribute("music", saveMusic.c_str());
5384 }
5385 }
5386
5387 /*
5388 XMLElement *level = doc.NewElement("Level");
5389 level->SetAttribute("elementTemplatePack", elementTemplatePack);
5390 if (bg)
5391 {
5392 int pos = bg->texture->name.find_last_of('/')+1;
5393 int pos2 = bg->texture->name.find_last_of('.');
5394 level->SetAttribute("bg", bg->texture->name.substr(pos, pos2-pos));
5395 std::ostringstream os;
5396 os << sceneColor.x << " " << sceneColor.y << " " << sceneColor.z;
5397 level->SetAttribute("sceneColor", os.str());
5398 }
5399 saveFile->InsertEndChild(level);
5400 */
5401
5402 std::ostringstream obs;
5403 int i = 0;
5404 for (i = 0; i < obsRows.size(); i++)
5405 {
5406 obs << obsRows[i].tx << " " << obsRows[i].ty << " " << obsRows[i].len << " ";
5407 }
5408 XMLElement *obsXml = saveFile.NewElement("Obs");
5409 obsXml->SetAttribute("d", obs.str().c_str());
5410 saveFile.InsertEndChild(obsXml);
5411
5412
5413 for (i = 0; i < dsq->game->getNumPaths(); i++)
5414 {
5415 XMLElement *pathXml = saveFile.NewElement("Path");
5416 Path *p = dsq->game->getPath(i);
5417 pathXml->SetAttribute("name", p->name.c_str());
5418 //pathXml->SetAttribute("active", p->active);
5419 for (int n = 0; n < p->nodes.size(); n++)
5420 {
5421 XMLElement *nodeXml = saveFile.NewElement("Node");
5422 std::ostringstream os;
5423 os << int(p->nodes[n].position.x) << " " << int(p->nodes[n].position.y);
5424 nodeXml->SetAttribute("pos", os.str().c_str());
5425 std::ostringstream os2;
5426 os2 << p->rect.getWidth() << " " << p->rect.getHeight();
5427 nodeXml->SetAttribute("rect", os2.str().c_str());
5428 nodeXml->SetAttribute("shape", (int)p->pathShape);
5429 if (p->nodes[n].maxSpeed != -1)
5430 {
5431 nodeXml->SetAttribute("ms", p->nodes[n].maxSpeed);
5432 }
5433 pathXml->InsertEndChild(nodeXml);
5434 }
5435 saveFile.InsertEndChild(pathXml);
5436 }
5437
5438 for (i = 0; i < dsq->game->warpAreas.size(); i++)
5439 {
5440 WarpArea a = dsq->game->warpAreas[i];
5441 XMLElement *waSF = saveFile.NewElement("WarpArea");
5442 waSF->SetAttribute("x", a.position.x);
5443 waSF->SetAttribute("y", a.position.y);
5444 if (a.radius > 0)
5445 waSF->SetAttribute("radius", a.radius);
5446 else if (a.w > 0 && a.h > 0)
5447 {
5448 waSF->SetAttribute("w", a.w);
5449 waSF->SetAttribute("h", a.h);
5450 }
5451 if (a.generated)
5452 {
5453 waSF->SetAttribute("g", 1);
5454 }
5455 std::ostringstream os;
5456 os << a.sceneName << " " << a.warpAreaType << " " << a.spawnOffset.x << " " << a.spawnOffset.y;
5457 waSF->SetAttribute("scene", os.str().c_str());
5458
5459 saveFile.InsertEndChild(waSF);
5460 }
5461
5462 std::ostringstream simpleElements[LR_MAX];
5463 std::ostringstream simpleElements_repeatScale[LR_MAX];
5464
5465
5466 for (i = 0; i < dsq->getNumElements(); i++)
5467 {
5468 Element *e = dsq->getElement(i);
5469 std::ostringstream& SE = simpleElements[e->bgLayer];
5470 SE << e->templateIdx << " "
5471 << int(e->position.x) << " "
5472 << int(e->position.y) << " "
5473 << int(e->rotation.z) << " "
5474 << e->scale.x << " "
5475 << e->scale.y << " "
5476 << int(e->isfh()) << " "
5477 << int(e->isfv()) << " "
5478 << e->elementFlag << " "
5479 << e->getElementEffectIndex()<< " "
5480 << e->isRepeatingTextureToFill() << " ";
5481
5482 if(e->isRepeatingTextureToFill())
5483 {
5484 std::ostringstream& SE_rs = simpleElements_repeatScale[e->bgLayer];
5485 SE_rs << e->repeatToFillScale.x << " "
5486 << e->repeatToFillScale.y << " ";
5487 }
5488 }
5489
5490 if (dsq->game->entitySaveData.size() > 0)
5491 {
5492 XMLElement *entitiesNode = saveFile.NewElement("Entities");
5493
5494 std::ostringstream os;
5495 for (int i = 0; i < dsq->game->entitySaveData.size(); i++)
5496 {
5497 EntitySaveData *e = &dsq->game->entitySaveData[i];
5498 os << e->idx << " ";
5499
5500 if (e->idx == -1)
5501 {
5502 if (!e->name.empty())
5503 os << e->name << " ";
5504 else
5505 os << "INVALID" << " ";
5506 }
5507 // group ID no longer used
5508 os << e->x << " " << e->y << " " << e->rot << " " << 0 << " " << e->id << " ";
5509 }
5510 entitiesNode->SetAttribute("j", os.str().c_str());
5511 saveFile.InsertEndChild(entitiesNode);
5512 }
5513
5514 for (i = 0; i < LR_MAX; i++)
5515 {
5516 std::string s = simpleElements[i].str();
5517 if (!s.empty())
5518 {
5519 XMLElement *simpleElementsXML = saveFile.NewElement("SE");
5520 simpleElementsXML->SetAttribute("k", s.c_str());
5521 simpleElementsXML->SetAttribute("l", i);
5522 std::string repeatScaleStr = simpleElements_repeatScale[i].str();
5523 if(!repeatScaleStr.empty())
5524 simpleElementsXML->SetAttribute("repeatScale", repeatScaleStr.c_str());
5525 saveFile.InsertEndChild(simpleElementsXML);
5526 }
5527 }
5528
5529 // HACK: fix this later (won't save light shafts)
5530 /*
5531 for (Core::RenderObjects::iterator i = core->renderObjects.begin(); i != core->renderObjects.end(); i++)
5532 {
5533 LightShaft *l = dynamic_cast<LightShaft*>(*i);
5534 if (l)
5535 {
5536 XMLElement *lightShaft = saveFile.NewElement("LightShaft");
5537 lightShaft->SetAttribute("x", l->position.x);
5538 lightShaft->SetAttribute("y", l->position.y);
5539 std::ostringstream os;
5540 os << l->getDir().x;
5541 lightShaft->SetAttribute("dirx", os.str());
5542 std::ostringstream os2;
5543 os2 << l->getDir().y;
5544 lightShaft->SetAttribute("diry", os2.str());
5545 std::ostringstream os3;
5546 os3 << l->shaftWidth;
5547 lightShaft->SetAttribute("w", os3.str());
5548
5549 //lightShaft->SetAttribute("dirx", int(l->getDir().x*1000));
5550 //lightShaft->SetAttribute("diry", int(l->getDir().y*1000));
5551 saveFile.InsertEndChild(lightShaft);
5552 }
5553 }
5554 */
5555
5556 bool result = saveFile.SaveFile(fn.c_str()) == XML_SUCCESS;
5557 if (result)
5558 debugLog("Successfully saved map: " + fn);
5559 else
5560 debugLog("Failed to save map: " + fn);
5561
5562 return result;
5563 }
5564
warpToArea(WarpArea * area)5565 void Game::warpToArea(WarpArea *area)
5566 {
5567 if (this->miniMapHint.scene == area->sceneName && this->miniMapHint.warpAreaType == area->warpAreaType)
5568 {
5569 miniMapHint.clear();
5570 }
5571 //positionToAvatar = area->avatarPosition;
5572 dsq->game->warpAreaType = area->warpAreaType;
5573 dsq->game->spawnOffset = area->spawnOffset;
5574 //dsq->game->warpAreaSide = area->;
5575 dsq->game->transitionToScene(area->sceneName);
5576 }
5577
createGradient()5578 void Game::createGradient()
5579 {
5580 if (grad)
5581 {
5582 grad->safeKill();
5583 grad = 0;
5584 }
5585 if (!grad)
5586 {
5587 grad = new Gradient;
5588 {
5589 //grad->makeVertical(Vector(0.6, 0.75, 0.65), Vector(0.4, 0.6, 0.5));
5590 //grad->makeVertical(Vector(0.6, 0.8, 0.65), Vector(0.1, 0.2, 0.4));
5591 grad->makeVertical(gradTop, gradBtm);
5592 grad->autoWidth = AUTO_VIRTUALWIDTH;
5593 grad->autoHeight = AUTO_VIRTUALHEIGHT;
5594 //grad->scale = Vector(core->getVirtualWidth(), core->getVirtualHeight());
5595 grad->position = Vector(400,300,-4);
5596 grad->followCamera = 1;
5597 grad->alpha = 1;
5598 grad->toggleCull(false);
5599 }
5600 addRenderObject(grad, LR_BACKDROP);
5601 if (bg)
5602 bg->blendEnabled = true;
5603 if (bg2)
5604 bg2->blendEnabled = true;
5605 }
5606 }
5607
isInGameMenu()5608 bool Game::isInGameMenu()
5609 {
5610 return inGameMenu;
5611 }
5612
isValidTarget(Entity * e,Entity * me)5613 bool Game::isValidTarget(Entity *e, Entity *me)
5614 {
5615 //(e->layer == LR_ENTITIES0 || e->layer == LR_ENTITIES || e->layer == LR_ENTITIES2)
5616 //&& true
5617 return (e != me && e->isNormalLayer() && e->isPresent() && e->getEntityType() == ET_ENEMY && e->isAvatarAttackTarget());
5618 }
5619
updateMiniMapHintPosition()5620 void Game::updateMiniMapHintPosition()
5621 {
5622 miniMapHintPosition = Vector(0,0,0);
5623 for (int i = 0; i < warpAreas.size(); i++)
5624 {
5625 if (this->sceneName == miniMapHint.scene)
5626 {
5627 if (warpAreas[i].warpAreaType == miniMapHint.warpAreaType)
5628 {
5629 miniMapHintPosition = warpAreas[i].position;
5630 }
5631 }
5632 else
5633 {
5634 if (warpAreas[i].sceneName == miniMapHint.scene)
5635 {
5636 miniMapHintPosition = warpAreas[i].position;
5637 }
5638 }
5639 }
5640 }
5641
createPets()5642 void Game::createPets()
5643 {
5644 setActivePet(dsq->continuity.getFlag(FLAG_PET_ACTIVE));
5645 }
5646
setActivePet(int flag)5647 Entity* Game::setActivePet(int flag)
5648 {
5649 if (currentPet)
5650 {
5651 currentPet->safeKill();
5652 currentPet = 0;
5653 }
5654
5655 dsq->continuity.setFlag(FLAG_PET_ACTIVE, flag);
5656
5657 if (flag != 0)
5658 {
5659
5660 int petv = flag - FLAG_PET_NAMESTART;
5661
5662 PetData *p = dsq->continuity.getPetData(petv);
5663 if (p)
5664 {
5665 std::string name = p->namePart;
5666
5667 Entity *e = createEntity("Pet_" + name, -1, avatar->position, 0, false, "");
5668 if (e)
5669 {
5670 currentPet = e;
5671 e->setState(Entity::STATE_FOLLOW, -1, true);
5672 e->postInit();
5673 }
5674 }
5675 }
5676
5677 return currentPet;
5678 }
5679
createLi()5680 void Game::createLi()
5681 {
5682 int liFlag = dsq->continuity.getFlag(FLAG_LI);
5683 std::ostringstream os;
5684 os << "liFlag: " << liFlag;
5685 debugLog(os.str());
5686
5687 if (liFlag == 100)
5688 {
5689 debugLog("Creating Li");
5690 li = createEntity("Li", 0, Vector(0,0), 0, false, "");
5691 //li->skeletalSprite.animate("idle");
5692 }
5693 }
5694
colorTest()5695 void Game::colorTest()
5696 {
5697 // test element coloring
5698 // possibly useful for darker maps
5699 /*
5700 std::vector<QuadLight> quadLights;
5701 quadLights.push_back(QuadLight(Vector(400, 300), Vector(1, 0, 0), 2000));
5702 for (int i = 0; i < dsq->getNumElements(); i++)
5703 {
5704 Element *e = dsq->getElement(i);
5705 //e->color = Vector(rand()%100, rand()%100, rand()%100);
5706 for (int i = 0; i < quadLights.size(); i++)
5707 {
5708 QuadLight *q = &quadLights[i];
5709 Vector dist = e->position - q->position;
5710 if (dist.isLength2DIn(q->dist))
5711 {
5712 float fract = float(dist.getLength2D())/float(quadLights[i].dist);
5713 float amb = fract;
5714 fract = 1.0f - fract;
5715 e->color = Vector(1,1,1)*amb + q->color*fract;
5716 }
5717 else
5718 {
5719 e->color = Vector(1,1,0);
5720 }
5721 }
5722 //e->color.normalize2D();
5723 }
5724 */
5725 }
5726
showImage(const std::string & gfx)5727 void Game::showImage(const std::string &gfx)
5728 {
5729 if (!image)
5730 {
5731 //float t = lua_tonumber(L, 2);
5732
5733 dsq->overlay->color = Vector(1,1,1);
5734 dsq->fade(1, 0.5);
5735 dsq->watch(0.5);
5736
5737 image = new Quad;
5738 image->setTexture(gfx);
5739 image->position = Vector(400,300);
5740 image->setWidthHeight(800, 800);
5741 image->offset = Vector(0,100);
5742 image->alpha = 0;
5743 image->followCamera = 1;
5744 core->addRenderObject(image, LR_HUD);
5745
5746 image->scale = Vector(1,1);
5747 image->scale.interpolateTo(Vector(1.1, 1.1), 12);
5748
5749 image->alpha = 1;
5750 dsq->fade(0, 0.5);
5751 }
5752 }
5753
hideImage()5754 void Game::hideImage()
5755 {
5756 if (image)
5757 {
5758 image->setLife(1);
5759 image->setDecayRate(1.0f/2.0f);
5760 image->fadeAlphaWithLife = 1;
5761 }
5762
5763 image = 0;
5764 dsq->overlay->color = 0;
5765 }
5766
switchBgLoop(int v)5767 void Game::switchBgLoop(int v)
5768 {
5769 if (v != lastBgSfxLoop)
5770 {
5771 if (dsq->loops.bg != BBGE_AUDIO_NOCHANNEL)
5772 {
5773 core->sound->fadeSfx(dsq->loops.bg, SFT_OUT, 0.5);
5774 dsq->loops.bg = BBGE_AUDIO_NOCHANNEL;
5775 }
5776
5777 switch(v)
5778 {
5779 case 0:
5780 if (!bgSfxLoop.empty())
5781 {
5782 PlaySfx sfx;
5783 sfx.name = bgSfxLoop;
5784 sfx.vol = bgSfxVol;
5785 sfx.loops = -1;
5786 sfx.priority = 0.8;
5787 dsq->loops.bg = core->sound->playSfx(sfx);
5788 }
5789 break;
5790 case 1:
5791 if (!airSfxLoop.empty())
5792 {
5793 PlaySfx sfx;
5794 sfx.name = airSfxLoop;
5795 sfx.vol = bgSfxVol;
5796 sfx.loops = -1;
5797 sfx.priority = 0.8;
5798 dsq->loops.bg = core->sound->playSfx(sfx);
5799 }
5800 break;
5801 }
5802 lastBgSfxLoop = v;
5803 }
5804 }
5805
entityDied(Entity * eDead)5806 void Game::entityDied(Entity *eDead)
5807 {
5808 Entity *e = 0;
5809 FOR_ENTITIES(i)
5810 {
5811 e = *i;
5812 if (e != eDead && e->isv(EV_ENTITYDIED,1))
5813 {
5814 e->entityDied(eDead);
5815 }
5816 }
5817
5818 dsq->continuity.entityDied(eDead);
5819 }
5820
postInitEntities()5821 void Game::postInitEntities()
5822 {
5823 FOR_ENTITIES(i)
5824 {
5825 Entity *e = *i;
5826 if (e)
5827 {
5828 e->postInit();
5829 }
5830 }
5831 core->resetTimer();
5832 }
5833
updateParticlePause()5834 void Game::updateParticlePause()
5835 {
5836 if (this->isPaused())
5837 {
5838 core->particlesPaused = 2;
5839 }
5840 else if (this->isWorldPaused())
5841 {
5842 core->particlesPaused = 1;
5843 }
5844 else
5845 {
5846 core->particlesPaused = 0;
5847 }
5848 }
5849
game_collideParticle(Vector pos)5850 int game_collideParticle(Vector pos)
5851 {
5852 bool aboveWaterLine = (pos.y <= dsq->game->waterLevel.x+20);
5853 bool inWaterBubble = false;
5854 if (!aboveWaterLine)
5855 {
5856 Path *p = dsq->game->getNearestPath(pos, PATH_WATERBUBBLE);
5857 if (p && p->active)
5858 {
5859 if (p->isCoordinateInside(pos))
5860 {
5861 inWaterBubble = true;
5862 }
5863 }
5864 }
5865 if (!inWaterBubble && aboveWaterLine)
5866 {
5867 return 1;
5868 }
5869
5870 TileVector t(pos);
5871 return dsq->game->isObstructed(t);
5872 }
5873
game_wibbleParticle(Particle * p)5874 void game_wibbleParticle(Particle *p)
5875 {
5876 /*
5877 if (dsq->game->avatar->getNotesOpen() > 0 && (p->position - dsq->game->avatar->position).isLength2DIn(256))
5878 {
5879 if (!p->offset.isInterpolating())
5880 {
5881 p->offset.interpolateTo(Vector(10,0), (8-dsq->game->avatar->getLastNote())/10.0f, -1, 1);
5882
5883 //if (dsq->game->avatar->isSinging())
5884 //{
5885 // p->influenceVariable = 1;
5886 // p->color.interpolateTo(dsq->getNoteColor(dsq->game->avatar->getLastNote()), 1.0);
5887 //}
5888
5889 }
5890 else
5891 {
5892 }
5893 }
5894 else
5895 {
5896 p->offset.stop();
5897
5898 //if (p->influenceVariable)
5899 // p->color.interpolateTo(Vector(1,1,1), 1);
5900
5901 }
5902 */
5903 }
5904
rebuildElementUpdateList()5905 void Game::rebuildElementUpdateList()
5906 {
5907 for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS8; i++)
5908 dsq->getRenderObjectLayer(i)->update = false;
5909
5910 elementUpdateList.clear();
5911 elementInteractionList.clear();
5912 for (int i = 0; i < dsq->getNumElements(); i++)
5913 {
5914 Element *e = dsq->getElement(i);
5915 const int eeidx = e->getElementEffectIndex();
5916 if (eeidx != -1 && e->layer >= LR_ELEMENTS1 && e->layer <= LR_ELEMENTS8)
5917 elementUpdateList.push_back(e);
5918 ElementEffect ee = dsq->getElementEffectByIndex(eeidx);
5919 if(ee.type == EFX_WAVY)
5920 elementInteractionList.push_back(e);
5921 }
5922 }
5923
setElementLayerFlags()5924 void Game::setElementLayerFlags()
5925 {
5926 for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS16; i++)
5927 {
5928 // FIXME: Background SchoolFish get added to ELEMENTS11, so
5929 // we can't optimize that layer. (Maybe create a new layer?)
5930 if (i == LR_ELEMENTS11)
5931 continue;
5932
5933 dsq->getRenderObjectLayer(i)->setOptimizeStatic(!isSceneEditorActive() && dsq->user.video.displaylists);
5934 }
5935 }
5936
getTimer(float mod)5937 float Game::getTimer(float mod)
5938 {
5939 return timer*mod;
5940 }
5941
getHalf2WayTimer(float mod)5942 float Game::getHalf2WayTimer(float mod)
5943 {
5944 float t=timer;
5945 if (t > 0.5f)
5946 t = 1 - t;
5947 return timer*2*mod;
5948 }
5949
getHalfTimer(float mod)5950 float Game::getHalfTimer(float mod)
5951 {
5952 return halfTimer*mod;
5953 }
5954
action(int id,int state)5955 void Game::action(int id, int state)
5956 {
5957 for (int i = 0; i < paths.size(); i++)
5958 {
5959 if (paths[i]->catchActions)
5960 {
5961 if (!paths[i]->action(id, state))
5962 break;
5963 }
5964 }
5965
5966 if(isIgnoreAction((AquariaActions)id))
5967 return;
5968
5969 if (id == ACTION_TOGGLEHELPSCREEN && !state)
5970 {
5971 onToggleHelpScreen();
5972 //toggleHelpScreen(!inHelpScreen);
5973 }
5974 if (id == ACTION_ESC && !state) onPressEscape();
5975 if (id == ACTION_PRIMARY && !state) onLeftMouseButton();
5976 if (id == ACTION_TOGGLEMENU)
5977 {
5978 if(state)
5979 showInGameMenu();
5980 else
5981 hideInGameMenu();
5982 }
5983 if (id == ACTION_TOGGLEWORLDMAP && !state)
5984 {
5985 if (foodMenu)
5986 {
5987 recipes->setFocus(true);
5988 recipeMenu.toggle(!recipeMenu.on, true);
5989 }
5990 else if (!core->isStateJumpPending())
5991 {
5992 toggleWorldMap();
5993 }
5994 }
5995
5996 #ifdef AQUARIA_BUILD_SCENEEDITOR
5997 if (id == ACTION_TOGGLESCENEEDITOR && !state) toggleSceneEditor();
5998 #endif
5999
6000 if (dsq->isDeveloperKeys() || isSceneEditorActive())
6001 {
6002 if (id == ACTION_TOGGLEGRID && !state) toggleGridRender();
6003 }
6004
6005 if (isInGameMenu())
6006 {
6007 if (treasureMenu)
6008 {
6009 if (!state && !dsq->isNested())
6010 {
6011 if (dsq->menuSelectDelay == 0)
6012 {
6013 if (id == ACTION_PREVPAGE)
6014 {
6015 dsq->menuSelectDelay = MENUSELECTDELAY;
6016 onPrevTreasurePage();
6017 //menu[5]->setFocus(true);
6018 }
6019 if (id == ACTION_NEXTPAGE)
6020 {
6021 dsq->menuSelectDelay = MENUSELECTDELAY;
6022 onNextTreasurePage();
6023 //menu[5]->setFocus(true);
6024 }
6025 }
6026 }
6027 }
6028 else if (foodMenu)
6029 {
6030 if (!state && !dsq->isNested())
6031 {
6032 if (dsq->menuSelectDelay == 0)
6033 {
6034 if (id == ACTION_PREVPAGE)
6035 {
6036 dsq->menuSelectDelay = MENUSELECTDELAY;
6037 if (recipeMenu.on)
6038 recipeMenu.goPrevPage();
6039 else
6040 onPrevFoodPage();
6041 }
6042 if (id == ACTION_NEXTPAGE)
6043 {
6044 dsq->menuSelectDelay = MENUSELECTDELAY;
6045 if (recipeMenu.on)
6046 recipeMenu.goNextPage();
6047 else
6048 onNextFoodPage();
6049 }
6050 }
6051
6052 if (id == ACTION_COOKFOOD)
6053 {
6054 if (!recipeMenu.on)
6055 onCook();
6056 }
6057
6058 if (id == ACTION_FOODLEFT)
6059 {
6060 if (recipeMenu.on)
6061 {
6062 }
6063 else
6064 {
6065 for (int i = 0; i < foodHolders.size(); i++)
6066 {
6067 if (!foodHolders[i]->isTrash() && !foodHolders[i]->isEmpty())
6068 {
6069 foodHolders[i]->dropFood();
6070 break;
6071 }
6072 }
6073 }
6074 }
6075
6076 if (id == ACTION_FOODRIGHT)
6077 {
6078 if (recipeMenu.on)
6079 {
6080 }
6081 else
6082 {
6083 for (int i = 0; i < foodSlots.size(); i++)
6084 {
6085 if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient())
6086 {
6087 foodSlots[i]->moveRight();
6088 break;
6089 }
6090 }
6091 }
6092 }
6093
6094 if (id == ACTION_FOODDROP)
6095 {
6096 if (recipeMenu.on)
6097 {
6098 }
6099 else
6100 {
6101 int trashIndex = -1;
6102 for (int i = 0; i < foodHolders.size(); i++)
6103 {
6104 if (foodHolders[i]->alpha.x > 0 && foodHolders[i]->alphaMod > 0 && foodHolders[i]->isTrash())
6105 {
6106 trashIndex = i;
6107 break;
6108 }
6109 }
6110 if (trashIndex >= 0)
6111 {
6112 int ingrIndex = -1;
6113 for (int i = 0; i < foodSlots.size(); i++)
6114 {
6115 if (foodSlots[i]->isCursorIn() && foodSlots[i]->getIngredient())
6116 {
6117 ingrIndex = i;
6118 break;
6119 }
6120 }
6121 if (ingrIndex >= 0)
6122 {
6123 foodSlots[ingrIndex]->discard();
6124 }
6125 }
6126 }
6127 }
6128 }
6129 }
6130 }
6131 }
6132
toggleWorldMap()6133 void Game::toggleWorldMap()
6134 {
6135 if (worldMapRender)
6136 {
6137 worldMapRender->toggle(!worldMapRender->isOn());
6138 }
6139 }
6140
applyState()6141 void Game::applyState()
6142 {
6143 bool verbose = true;
6144 applyingState = true;
6145
6146 helpText = 0;
6147 helpUp = helpDown = 0;
6148 inHelpScreen = false;
6149 helpBG = 0;
6150 helpBG2 = 0;
6151
6152 dsq->returnToScene = "";
6153
6154 // new place where mods get stopped!
6155 // this lets recaching work
6156 // (presumably because there has been time for the garbage to be cleared)
6157 if (sceneToLoad == "title" && dsq->mod.isShuttingDown())
6158 {
6159 if (dsq->mod.isActive())
6160 {
6161 dsq->mod.stop();
6162 dsq->continuity.reset();
6163 }
6164 }
6165
6166 dsq->collectScriptGarbage();
6167
6168 isCooking = false;
6169 enqueuedPreviewRecipe = 0;
6170
6171 dsq->toggleBlackBars(false);
6172
6173 dsq->setTexturePointers();
6174
6175
6176 moveFoodSlotToFront = 0;
6177
6178 cameraOffBounds = false;
6179
6180
6181 ingOffY = 0;
6182 ingOffYTimer = 0;
6183
6184 AquariaGuiElement::canDirMoveGlobal = true;
6185
6186 cookDelay = 0;
6187
6188 dsq->toggleVersionLabel(false);
6189
6190 activation = true;
6191
6192 active = true;
6193
6194 hasPlayedLow = false;
6195
6196 firstSchoolFish = true;
6197 invincibleOnNested = true;
6198
6199
6200 controlHintNotes.clear();
6201
6202 worldMapIndex = -1;
6203
6204 particleManager->setNumSuckPositions(10);
6205
6206 dropIngrNames.clear();
6207
6208 foodMenu = optionsMenu = petMenu = treasureMenu = false;
6209
6210 currentPet = 0;
6211
6212 bgSfxLoopPlaying2 = "";
6213 lastBgSfxLoop = -1;
6214 saveMusic = "";
6215
6216 timer = 0;
6217 halfTimer = 0;
6218
6219 cameraFollowObject = 0;
6220 cameraFollowEntity = 0;
6221
6222 shuttingDownGameState = false;
6223 core->particlesPaused = false;
6224 bNatural = false;
6225 songLineRender = 0;
6226 image = 0;
6227
6228 core->particleManager->collideFunction = game_collideParticle;
6229 core->particleManager->specialFunction = game_wibbleParticle;
6230
6231 controlHint_ignoreClear = false;
6232 inGameMenuExitState = 0;
6233 int i = 0;
6234 debugLog("Entering Game::applyState");
6235 dsq->overlay->alpha = 1;
6236 dsq->overlay->color = 0;
6237
6238
6239 for (i = LR_ELEMENTS1; i <= LR_ELEMENTS12; i++) // LR_ELEMENTS13 is darkness, stop before that
6240 {
6241 dsq->game->setElementLayerVisible(i-LR_ELEMENTS1, true);
6242 }
6243
6244 dsq->applyParallaxUserSettings();
6245
6246 controlHintTimer = 0;
6247 cameraConstrained = true;
6248 // reset parallax
6249 RenderObjectLayer *l = 0;
6250 for (i = LR_ELEMENTS10; i <= LR_ELEMENTS16; i++)
6251 {
6252 l = &dsq->renderObjectLayers[i];
6253 l->followCamera = 0;
6254 l->followCameraLock = 0;
6255 }
6256
6257 dsq->resetLayerPasses();
6258
6259 ignoredActions.clear();
6260
6261 cameraLerpDelay = 0;
6262 playingSongInMenu = -1;
6263 sceneColor2 = Vector(1,1,1);
6264 sceneColor3 = Vector(1,1,1);
6265 if (core->afterEffectManager)
6266 {
6267 core->afterEffectManager->clear();
6268 //core->afterEffectManager->addEffect(new RippleEffect());
6269 }
6270 Shot::shots.clear(); // the shots were deleted elsewhere, drop any remaining pointers
6271 Shot::deleteShots.clear();
6272 backdropQuad = 0;
6273 clearObsRows();
6274 inGameMenu = false;
6275 sceneFlipped = false;
6276 useWaterLevel = false;
6277 waterLevel = saveWaterLevel = 0;
6278 //miniMapHintPosition = Vector(8900, 14520);
6279 currentInventoryPage = 0;
6280
6281 dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = false;
6282
6283 //dsq->getRenderObjectLayer(LR_ELEMENTS5)->update = false;
6284
6285 backgroundImageRepeat = 1;
6286 grad = 0;
6287 maxZoom = -1;
6288 maxLookDistance = 600;
6289 saveFile = 0;
6290 deathTimer = 0.9;
6291 runGameOverScript = false;
6292 paused = false;
6293 //sceneColor = Vector(0.75, 0.75, 0.8);
6294 sceneColor = Vector(1,1,1);
6295 sceneName = "";
6296 elementTemplatePack ="";
6297 clearGrid();
6298 clearPointers();
6299 SkeletalSprite::clearCache();
6300
6301
6302 StateObject::applyState();
6303 //core->enable2D(800);
6304
6305 dsq->clearEntities();
6306 dsq->clearElements();
6307 elementWithMenu = 0;
6308 //dsq->gui.menu.clearEntries();
6309
6310
6311 progressBar = 0;
6312
6313 /*
6314 progressBar = new AquariaProgressBar();
6315 {
6316 progressBar->position = Vector(400,300);
6317 }
6318 addRenderObject(progressBar, LR_PROGRESS);
6319 */
6320
6321 damageSprite = new Quad;
6322 {
6323 damageSprite->setTexture("damage");
6324 damageSprite->alpha = 0;
6325 damageSprite->autoWidth = AUTO_VIRTUALWIDTH;
6326 damageSprite->autoHeight = AUTO_VIRTUALHEIGHT;
6327 damageSprite->position = Vector(400,300);
6328 damageSprite->followCamera = true;
6329 damageSprite->scale.interpolateTo(Vector(1.1, 1.1), 0.75, -1, 1, 1);
6330 }
6331 addRenderObject(damageSprite, LR_DAMAGESPRITE);
6332
6333 bg2 = new Quad;
6334 {
6335 bg2->position = Vector(400, 300, -3/*-0.09f*/);
6336 //bg2->color = Vector(0.9, 0.9, 0.9);
6337 bg2->setTexture("missingImage");
6338 bg2->setWidthHeight(900,600);
6339 //bg2->blendEnabled = false;
6340 bg2->followCamera =1;
6341 bg2->alpha = 0.8;
6342 }
6343 addRenderObject(bg2, LR_BACKGROUND);
6344
6345 bg = new Quad;
6346 {
6347 bg->blendEnabled = false;
6348 bg->position = Vector(400, 300, -2/*-0.09f*/);
6349 //bg->color = Vector(0.9, 0.9, 0.9);
6350 bg->setTexture("missingImage");
6351 bg->setWidthHeight(900,600);
6352 //bg->blendEnabled = true;
6353 bg->followCamera =1;
6354 bg->alpha = 1;
6355 }
6356 addRenderObject(bg, LR_BACKGROUND);
6357
6358
6359 Vector mousePos(400,490);
6360
6361 controlHint_bg = new Quad;
6362 {
6363 controlHint_bg->followCamera = 1;
6364 controlHint_bg->position = Vector(400,500);
6365 controlHint_bg->color = 0;
6366 controlHint_bg->alphaMod = 0.7;
6367 //controlHint_bg->setTexture("HintBox");
6368 controlHint_bg->setWidthHeight(core->getVirtualWidth(), 100);
6369 controlHint_bg->autoWidth = AUTO_VIRTUALWIDTH;
6370 controlHint_bg->alpha = 0;
6371 }
6372 addRenderObject(controlHint_bg, LR_HELP);
6373
6374 controlHint_text = new BitmapText(&dsq->smallFont);
6375 {
6376 controlHint_text->alpha = 0;
6377 controlHint_text->setWidth(700);
6378
6379 controlHint_text->setAlign(ALIGN_LEFT);
6380 controlHint_text->followCamera = 1;
6381 controlHint_text->scale = Vector(0.9, 0.9);
6382 //controlHint_text->setFontSize(14);
6383 }
6384 addRenderObject(controlHint_text, LR_HELP);
6385
6386 controlHint_image = new Quad;
6387 {
6388 controlHint_image->followCamera = 1;
6389 controlHint_image->position = mousePos;
6390 controlHint_image->alpha = 0;
6391 }
6392 addRenderObject(controlHint_image, LR_HELP);
6393
6394 controlHint_mouseLeft = new Quad;
6395 {
6396 controlHint_mouseLeft->followCamera = 1;
6397 controlHint_mouseLeft->setTexture("Mouse-LeftButton");
6398 controlHint_mouseLeft->position = mousePos;
6399 controlHint_mouseLeft->alpha = 0;
6400 }
6401 addRenderObject(controlHint_mouseLeft, LR_HELP);
6402
6403
6404 controlHint_mouseRight = new Quad;
6405 {
6406 controlHint_mouseRight->followCamera = 1;
6407 controlHint_mouseRight->setTexture("Mouse-RightButton");
6408 controlHint_mouseRight->position = mousePos;
6409 controlHint_mouseRight->alpha = 0;
6410 }
6411 addRenderObject(controlHint_mouseRight, LR_HELP);
6412
6413 controlHint_mouseMiddle = new Quad;
6414 {
6415 controlHint_mouseMiddle->followCamera = 1;
6416 controlHint_mouseMiddle->setTexture("Mouse-MiddleButton");
6417 controlHint_mouseMiddle->position = mousePos;
6418 controlHint_mouseMiddle->alpha = 0;
6419 }
6420 addRenderObject(controlHint_mouseMiddle, LR_HELP);
6421
6422 controlHint_mouseBody = new Quad;
6423 {
6424 controlHint_mouseBody->followCamera = 1;
6425 controlHint_mouseBody->setTexture("Mouse-Body");
6426 controlHint_mouseBody->position = mousePos;
6427 controlHint_mouseBody->alpha = 0;
6428 }
6429 addRenderObject(controlHint_mouseBody, LR_HELP);
6430
6431
6432 controlHint_shine = new Quad;
6433 {
6434 //controlHint_shine->setTexture("spiralglow");
6435 controlHint_shine->color = Vector(1,1,1);
6436 controlHint_shine->followCamera = 1;
6437 controlHint_shine->position = Vector(400,500);
6438 controlHint_shine->alphaMod = 0.3;
6439 controlHint_shine->setWidthHeight(core->getVirtualWidth(), 100);
6440 controlHint_shine->alpha = 0;
6441 controlHint_shine->setBlendType(RenderObject::BLEND_ADD);
6442 }
6443 addRenderObject(controlHint_shine, LR_HELP);
6444
6445 li = 0;
6446
6447
6448 #ifdef AQUARIA_BUILD_SCENEEDITOR
6449 if (dsq->canOpenEditor())
6450 {
6451 sceneEditor.init();
6452 }
6453 #endif
6454
6455 /*
6456 if (liFlag == 100)
6457 */
6458
6459 if (verbose) debugLog("Creating Avatar");
6460 avatar = new Avatar();
6461 if (verbose) debugLog("Done new Avatar");
6462
6463 if (warpAreaType.empty())
6464 {
6465 if (positionToAvatar.x == 0 && positionToAvatar.y == 0)
6466 avatar->position = Vector(dsq->avStart.x,dsq->avStart.y);
6467 else
6468 avatar->position = positionToAvatar;
6469 positionToAvatar = Vector(0,0);
6470 }
6471 if (verbose) debugLog("Done warp");
6472
6473 if (verbose) debugLog("Create Li");
6474 createLi();
6475 if (verbose) debugLog("Done");
6476
6477
6478
6479
6480 if (toFlip == 1)
6481 {
6482 dsq->game->avatar->flipHorizontal();
6483 toFlip = -1;
6484 }
6485
6486
6487
6488
6489
6490 // li
6491 //if (true)
6492
6493
6494 if (verbose) debugLog("WarpKeys");
6495
6496
6497
6498 if (verbose) debugLog("Done WarpKeys");
6499
6500 bindInput();
6501
6502 shapeDebug = 0;
6503
6504 /*
6505 shapeDebug = new Quad;
6506 shapeDebug->setWidthHeight(80, 80);
6507 shapeDebug->color = Vector(1,1,0);
6508 addRenderObject(shapeDebug, LR_ENTITIES);
6509 */
6510
6511
6512
6513 if (verbose) debugLog("Loading Scene");
6514 if (!loadScene(sceneToLoad))
6515 {
6516 loadElementTemplates(elementTemplatePack);
6517 }
6518 if (verbose) debugLog("...Done");
6519 backupSceneColor = sceneColor;
6520
6521 dsq->continuity.worldMap.revealMap(sceneName);
6522
6523 colorTest();
6524
6525 if (!warpAreaType.empty())
6526 {
6527 for (int i = 0; i < warpAreas.size(); i++)
6528 {
6529 WarpArea *a = &warpAreas[i];
6530 if (a->warpAreaType == warpAreaType)
6531 {
6532 int extra=96;
6533 if (a->radius)
6534 avatar->position = a->position + (spawnOffset*(a->radius+extra));
6535 else
6536 {
6537 Vector s(spawnOffset.x*(a->w+extra), spawnOffset.y*(a->h+extra));
6538 avatar->position = a->position + s;
6539 }
6540 break;
6541 }
6542 }
6543 warpAreaType = "";
6544 }
6545
6546
6547 if (verbose) debugLog("Adding Avatar");
6548 addRenderObject(avatar, LR_ENTITIES);
6549 //cameraFollow = &avatar->position;
6550 setCameraFollowEntity(avatar);
6551 if (verbose) debugLog("...Done");
6552
6553
6554 currentRender = new CurrentRender();
6555 addRenderObject(currentRender, LR_ELEMENTS3);
6556
6557 steamRender = new SteamRender();
6558 addRenderObject(steamRender, LR_ELEMENTS9);
6559
6560 songLineRender = new SongLineRender();
6561 addRenderObject(songLineRender, LR_HUD);
6562
6563 gridRender = new GridRender(OT_INVISIBLE);
6564 gridRender->color = Vector(1, 0, 0);
6565 addRenderObject(gridRender, LR_DEBUG_TEXT);
6566 gridRender->alpha = 0;
6567
6568 gridRender2 = new GridRender(OT_HURT);
6569 gridRender2->color = Vector(1, 1, 0);
6570 addRenderObject(gridRender2, LR_DEBUG_TEXT);
6571 gridRender2->alpha = 0;
6572
6573 gridRender3 = new GridRender(OT_INVISIBLEIN);
6574 gridRender3->color = Vector(1, 0.5f, 0);
6575 addRenderObject(gridRender3, LR_DEBUG_TEXT);
6576 gridRender3->alpha = 0;
6577
6578 edgeRender = new GridRender(OT_BLACKINVIS);
6579 edgeRender->color = Vector(0.3f, 0, 0.6f);
6580 addRenderObject(edgeRender, LR_DEBUG_TEXT);
6581 edgeRender->alpha = 0;
6582
6583 gridRenderEnt = new GridRender(OT_INVISIBLEENT);
6584 gridRenderEnt->color = Vector(0, 1, 0.5);
6585 addRenderObject(gridRenderEnt, LR_DEBUG_TEXT);
6586 gridRenderEnt->alpha = 0;
6587
6588 gridRenderUser1 = new GridRender(OT_USER1);
6589 addRenderObject(gridRenderUser1, LR_DEBUG_TEXT);
6590 gridRenderUser1->color = Vector(1, 0, 1);
6591 gridRenderUser1->alpha = 0;
6592
6593 gridRenderUser2 = new GridRender(OT_USER2);
6594 addRenderObject(gridRenderUser2, LR_DEBUG_TEXT);
6595 gridRenderUser2->color = Vector(1, 1, 1);
6596 gridRenderUser2->alpha = 0;
6597
6598 waterSurfaceRender = new WaterSurfaceRender();
6599 //waterSurfaceRender->setRenderPass(-1);
6600 addRenderObject(waterSurfaceRender, LR_WATERSURFACE);
6601
6602 GridRender *blackRender = new GridRender(OT_BLACK);
6603 blackRender->color = Vector(0, 0, 0);
6604 //blackRender->alpha = 0;
6605 blackRender->blendEnabled = false;
6606 addRenderObject(blackRender, LR_ELEMENTS4);
6607
6608
6609 hudUnderlay = new Quad;
6610 hudUnderlay->color = 0;
6611 hudUnderlay->position = Vector(400,300);
6612 //hudUnderlay->scale = Vector(800, 600);
6613 hudUnderlay->autoWidth = AUTO_VIRTUALWIDTH;
6614 hudUnderlay->autoHeight = AUTO_VIRTUALHEIGHT;
6615 hudUnderlay->alpha = 0;
6616 hudUnderlay->followCamera = 1;
6617 addRenderObject(hudUnderlay, LR_HUDUNDERLAY);
6618
6619 autoMap = 0;
6620 /*
6621 autoMap = new AutoMap;
6622 addRenderObject(autoMap, LR_MESSAGEBOX);
6623 */
6624
6625 miniMapRender = 0;
6626
6627 //miniMapRender->position = Vector(400,300);
6628
6629 miniMapRender = new MiniMapRender;
6630
6631 //miniMapRender->position = Vector(740,540);
6632 // position = (vw,vh) - (scale*100)
6633 // set in minimaprender::onupdate
6634 miniMapRender->scale = Vector(0.55, 0.55);
6635
6636
6637 /*
6638 miniMapRender->position = Vector(750,550);
6639 miniMapRender->scale = Vector(0.5, 0.5);
6640 */
6641
6642 //miniMapRender->scale = Vector(8,8);
6643 addRenderObject(miniMapRender, LR_MINIMAP);
6644
6645 timerText = new BitmapText(&dsq->smallFont);
6646 timerText->position = Vector(745, 550);
6647 timerText->alpha = 0;
6648 timerText->followCamera = 1;
6649 addRenderObject(timerText, LR_MINIMAP);
6650
6651 worldMapRender = 0;
6652
6653 if(dsq->mod.isActive() && dsq->mod.mapRevealMethod != REVEAL_UNSPECIFIED)
6654 WorldMapRender::setRevealMethod(dsq->mod.mapRevealMethod);
6655 else
6656 WorldMapRender::setRevealMethod((WorldMapRevealMethod)dsq->user.video.worldMapRevealMethod);
6657
6658 worldMapRender = new WorldMapRender;
6659 addRenderObject(worldMapRender, LR_WORLDMAP);
6660 // to hide minimap
6661 //miniMapRender->position += Vector(800,0);
6662
6663 sceneToLoad="";
6664
6665 if (!fromScene.empty())
6666 {
6667 stringToLower(fromScene);
6668 debugLog("fromScene: " + fromScene + " fromWarpType: " + fromWarpType);
6669 float smallestDist = HUGE_VALF;
6670 Path *closest = 0;
6671 Vector closestPushOut;
6672 bool doFlip = false;
6673 for (int i = 0; i < dsq->game->getNumPaths(); i++)
6674 {
6675 Path *p = dsq->game->getPath(i);
6676 Vector pos = p->nodes[0].position;
6677 if (p && (nocasecmp(p->warpMap, fromScene)==0))
6678 {
6679 float dist = -1;
6680 bool go = false;
6681 Vector pushOut;
6682 switch(fromWarpType)
6683 {
6684 case CHAR_RIGHT:
6685 go = (p->warpType == CHAR_LEFT);
6686 pushOut = Vector(1,0);
6687 dist = fabsf(fromPosition.y - pos.y);
6688 doFlip = true;
6689 break;
6690 case CHAR_LEFT:
6691 go = (p->warpType == CHAR_RIGHT);
6692 pushOut = Vector(-1,0);
6693 dist = fabsf(fromPosition.y - pos.y);
6694 break;
6695 case CHAR_UP:
6696 go = (p->warpType == CHAR_DOWN);
6697 pushOut = Vector(0, -1);
6698 dist = fabsf(fromPosition.x - pos.x);
6699 break;
6700 case CHAR_DOWN:
6701 go = (p->warpType == CHAR_UP);
6702 pushOut = Vector(0, 1);
6703 dist = fabsf(fromPosition.x - pos.x);
6704 break;
6705 }
6706 if (go)
6707 {
6708 if (dist == -1)
6709 {
6710 debugLog(p->warpMap + ": warpType is wonky");
6711 }
6712 else if (dist < smallestDist)
6713 {
6714 smallestDist = dist;
6715 closest = p;
6716 closestPushOut = pushOut;
6717 }
6718 }
6719 }
6720 }
6721 if (closest)
6722 {
6723 debugLog("warping avatar to node: " + closest->name);
6724 // this value of 8 is just nothing really
6725 // it short work with default value 1
6726 // just gives the player some room to move without heading straight back
6727 // into the warp
6728 // LOL to the above!!! :DDDDD
6729 avatar->position = closest->getEnterPosition(50);
6730 if (doFlip)
6731 avatar->flipHorizontal();
6732 /*
6733 avatar->position = closest->nodes[0].position;
6734 avatar->position += closestPushOut * 80;
6735 */
6736
6737 /*
6738 fromVel = Vector(0,1);
6739 avatar->rotateToVec(fromVel, 0.001);
6740 */
6741 }
6742 else
6743 {
6744 debugLog("ERROR: Could not find a node to warp the player to!");
6745 }
6746 fromScene = "";
6747 }
6748 else if (!toNode.empty())
6749 {
6750 Path *p = dsq->game->getPathByName(toNode);
6751 if (p)
6752 {
6753 avatar->position = p->nodes[0].position;
6754 }
6755 toNode = "";
6756 }
6757 /*
6758 if (!fromVel.isZero())
6759 {
6760 //avatar->vel = fromVel;
6761 avatar->rotateToVec(fromVel, 0.001);
6762 }
6763 */
6764
6765 avatar->setWasUnderWater();
6766 if (!avatar->isUnderWater())
6767 {
6768 avatar->setMaxSpeed(dsq->v.maxOutOfWaterSpeed);
6769 avatar->currentMaxSpeed = dsq->v.maxOutOfWaterSpeed;
6770 }
6771
6772 if (avatar->position.isZero() || avatar->position == Vector(1,1))
6773 {
6774 Path *p = 0;
6775 if ((p = getPathByName("NAIJASTART")) != 0 || (p = getPathByName("NAIJASTART L")) != 0)
6776 {
6777 avatar->position = p->nodes[0].position;
6778 }
6779 else if ((p = getPathByName("NAIJASTART R")) != 0)
6780 {
6781 avatar->position = p->nodes[0].position;
6782 avatar->flipHorizontal();
6783 }
6784 }
6785
6786
6787 //positionLi
6788 if (li)
6789 {
6790 li->position = avatar->position + Vector(8,8);
6791 }
6792
6793 toNode = "";
6794
6795 createInGameMenu();
6796 hideInGameMenu(false);
6797
6798 core->cacheRender();
6799
6800 cameraInterp.stop();
6801
6802 core->globalScale = dsq->continuity.zoom;
6803 //core->globalScaleChanged();
6804 avatar->myZoom = dsq->continuity.zoom;
6805
6806 cameraInterp = avatar->position;
6807 core->cameraPos = getCameraPositionFor(avatar->position);
6808
6809 core->sort();
6810
6811 if (dsq->mod.isActive())
6812 dsq->runScript(dsq->mod.getPath() + "scripts/premap_" + sceneName + ".lua", "init", true);
6813 else
6814 dsq->runScript("scripts/maps/premap_"+sceneName+".lua", "init", true);
6815
6816 std::string musicToPlay = this->musicToPlay;
6817 if (!overrideMusic.empty())
6818 {
6819 musicToPlay = overrideMusic;
6820 }
6821
6822 if(cookingScript)
6823 {
6824 dsq->scriptInterface.closeScript(cookingScript);
6825 cookingScript = NULL;
6826 }
6827
6828 if (dsq->mod.isActive())
6829 cookingScript = dsq->scriptInterface.openScript(dsq->mod.getPath() + "scripts/cooking.lua", true);
6830 else
6831 cookingScript = dsq->scriptInterface.openScript("scripts/global/cooking.lua", true);
6832
6833 //INFO: this used to be here to start fading out the music
6834 // before the level had begun
6835 /*
6836 if (dsq->sound->isPlayingMusic())
6837 {
6838 if (dsq->sound->currentMusic.find(musicToPlay) != std::string::npos)
6839 {
6840 }
6841 else
6842 {
6843 dsq->sound->fadeMusic(SFT_CROSS, 1);
6844 }
6845 }
6846 */
6847
6848 /*
6849 // HACK: to get the player on the map if there's an error with the warp coords
6850 while(dsq->game->collideCircleWithGrid(avatar->position, 32))
6851 {
6852 if (avatar->position.y < 200)
6853 avatar->position.y += 200;
6854 avatar->position += Vector(40,0);
6855 avatar->clampPosition();
6856 }
6857 */
6858
6859 updateMiniMapHintPosition();
6860
6861 createPets();
6862
6863
6864 postInitEntities();
6865
6866
6867 /*
6868 core->sound->musicVolume(1.0, 0.5);
6869 core->sound->sfxVolume(1.0, 0.5);
6870 */
6871
6872 bool musicchanged = updateMusic();
6873
6874
6875
6876 dsq->loops.bg = BBGE_AUDIO_NOCHANNEL;
6877
6878 if (!bgSfxLoop.empty())
6879 {
6880 core->sound->loadLocalSound(bgSfxLoop);
6881 }
6882
6883 if (!airSfxLoop.empty())
6884 {
6885 core->sound->loadLocalSound(airSfxLoop);
6886 }
6887
6888 if (dsq->continuity.getWorldType() != WT_NORMAL)
6889 dsq->continuity.applyWorldEffects(dsq->continuity.getWorldType(), 0, musicchanged);
6890
6891
6892 if (verbose) debugLog("initAvatar");
6893
6894 dsq->continuity.initAvatar(avatar);
6895
6896 if (verbose) debugLog("Done initAvatar");
6897
6898
6899 if (verbose) debugLog("reset timer");
6900 core->resetTimer();
6901
6902 if (verbose) debugLog("paths init");
6903 int pathSz = getNumPaths();
6904 for (i = 0; i < pathSz; i++)
6905 {
6906 getPath(i)->init();
6907 }
6908
6909 debugLog("Updating bgSfxLoop");
6910 updateBgSfxLoop();
6911
6912 // Must be _before_ the init script, since some init scripts run
6913 // cutscenes immediately. --achurch
6914 dsq->subtitlePlayer.show(0.25);
6915
6916 if (verbose) debugLog("loading map init script");
6917 if (dsq->mod.isActive())
6918 dsq->runScript(dsq->mod.getPath() + "scripts/map_" + sceneName + ".lua", "init", true);
6919 else
6920 dsq->runScript("scripts/maps/map_"+sceneName+".lua", "init", true);
6921
6922 if (!dsq->doScreenTrans && (dsq->overlay->alpha != 0 && !dsq->overlay->alpha.isInterpolating()))
6923 {
6924 if (verbose) debugLog("fading in");
6925 debugLog("FADEIN");
6926 //dsq->overlay->alpha = 1;
6927 dsq->overlay->alpha.interpolateTo(0, 1);
6928
6929 core->resetTimer();
6930 avatar->disableInput();
6931 core->main(0.5);
6932 avatar->enableInput();
6933 core->resetTimer();
6934 }
6935
6936 if (dsq->doScreenTrans)
6937 {
6938 debugLog("SCREENTRANS!");
6939 core->resetTimer();
6940 dsq->toggleCursor(false, 0);
6941 dsq->doScreenTrans = false;
6942
6943 dsq->transitionSaveSlots();
6944 dsq->overlay->alpha = 0;
6945 dsq->main(0.5);
6946 dsq->toggleCursor(true);
6947 dsq->tfader->alpha.interpolateTo(0, 0.2);
6948 dsq->main(0.21);
6949 dsq->clearSaveSlots(false);
6950 }
6951
6952 if (verbose) debugLog("reset timer");
6953
6954 applyingState = false;
6955
6956 if (!dsq->doScreenTrans)
6957 {
6958 dsq->toggleCursor(true, 0.5);
6959 }
6960
6961 dsq->forceInputGrabOff();
6962
6963 debugLog("Game::applyState Done");
6964 }
6965
bindInput()6966 void Game::bindInput()
6967 {
6968 if (!(this->applyingState || this->isActive())) return;
6969
6970 ActionMapper::clearActions();
6971 //ActionMapper::clearCreatedEvents();
6972
6973
6974 #ifdef AQUARIA_BUILD_SCENEEDITOR
6975 if (dsq->canOpenEditor())
6976 {
6977 addAction(ACTION_TOGGLESCENEEDITOR, KEY_TAB);
6978 }
6979 #endif
6980
6981
6982 dsq->user.control.actionSet.importAction(this, "PrimaryAction", ACTION_PRIMARY);
6983 dsq->user.control.actionSet.importAction(this, "SecondaryAction", ACTION_SECONDARY);
6984
6985 dsq->user.control.actionSet.importAction(this, "Escape", ACTION_ESC);
6986
6987 dsq->user.control.actionSet.importAction(this, "WorldMap", ACTION_TOGGLEWORLDMAP);
6988
6989 dsq->user.control.actionSet.importAction(this, "ToggleHelp", ACTION_TOGGLEHELPSCREEN);
6990
6991 // used for scrolling help text
6992 dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_SWIMUP);
6993 dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_SWIMDOWN);
6994 dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_SWIMLEFT);
6995 dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_SWIMRIGHT);
6996
6997
6998 dsq->user.control.actionSet.importAction(this, "PrevPage", ACTION_PREVPAGE);
6999 dsq->user.control.actionSet.importAction(this, "NextPage", ACTION_NEXTPAGE);
7000 dsq->user.control.actionSet.importAction(this, "CookFood", ACTION_COOKFOOD);
7001 dsq->user.control.actionSet.importAction(this, "FoodLeft", ACTION_FOODLEFT);
7002 dsq->user.control.actionSet.importAction(this, "FoodRight", ACTION_FOODRIGHT);
7003 dsq->user.control.actionSet.importAction(this, "FoodDrop", ACTION_FOODDROP);
7004
7005 if (dsq->canOpenEditor())
7006 {
7007 //addAction(MakeFunctionEvent(Game, toggleMiniMapRender), KEY_M, 0);
7008 addAction(ACTION_TOGGLEGRID, KEY_F9);
7009 }
7010
7011 /*
7012 addAction(ACTION_MENULEFT, KEY_LEFT);
7013 addAction(ACTION_MENURIGHT, KEY_RIGHT);
7014 addAction(ACTION_MENUUP, KEY_UP);
7015 addAction(ACTION_MENUDOWN, KEY_DOWN);
7016
7017 dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_MENULEFT);
7018 dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_MENURIGHT);
7019 dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_MENUUP);
7020 dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_MENUDOWN);
7021
7022 addAction(ACTION_MENULEFT, JOY1_DPAD_LEFT);
7023 addAction(ACTION_MENURIGHT, JOY1_DPAD_RIGHT);
7024 addAction(ACTION_MENUUP, JOY1_DPAD_UP);
7025 addAction(ACTION_MENUDOWN, JOY1_DPAD_DOWN);
7026 */
7027
7028 addAction(ACTION_MENULEFT, JOY1_STICK_LEFT);
7029 addAction(ACTION_MENURIGHT, JOY1_STICK_RIGHT);
7030 addAction(ACTION_MENUUP, JOY1_STICK_UP);
7031 addAction(ACTION_MENUDOWN, JOY1_STICK_DOWN);
7032
7033 // To capture quick song keys via script
7034 dsq->user.control.actionSet.importAction(this, "SongSlot1", ACTION_SONGSLOT1);
7035 dsq->user.control.actionSet.importAction(this, "SongSlot2", ACTION_SONGSLOT2);
7036 dsq->user.control.actionSet.importAction(this, "SongSlot3", ACTION_SONGSLOT3);
7037 dsq->user.control.actionSet.importAction(this, "SongSlot4", ACTION_SONGSLOT4);
7038 dsq->user.control.actionSet.importAction(this, "SongSlot5", ACTION_SONGSLOT5);
7039 dsq->user.control.actionSet.importAction(this, "SongSlot6", ACTION_SONGSLOT6);
7040 dsq->user.control.actionSet.importAction(this, "SongSlot7", ACTION_SONGSLOT7);
7041 dsq->user.control.actionSet.importAction(this, "SongSlot8", ACTION_SONGSLOT8);
7042 dsq->user.control.actionSet.importAction(this, "SongSlot9", ACTION_SONGSLOT9);
7043 dsq->user.control.actionSet.importAction(this, "SongSlot10", ACTION_SONGSLOT10);
7044
7045 dsq->user.control.actionSet.importAction(this, "Revert", ACTION_REVERT);
7046
7047 dsq->user.control.actionSet.importAction(this, "Look", ACTION_LOOK);
7048 dsq->user.control.actionSet.importAction(this, "Roll", ACTION_ROLL);
7049
7050 if (avatar)
7051 avatar->bindInput();
7052
7053 if (worldMapRender)
7054 worldMapRender->bindInput();
7055 }
7056
ingType(const std::vector<IngredientData * > & list,IngredientType type,int amount=1)7057 bool ingType(const std::vector<IngredientData*> &list, IngredientType type, int amount=1)
7058 {
7059 int c = 0;
7060 for (int i = 0; i < list.size(); i++)
7061 {
7062 IngredientData *data = list[i];
7063 if ((data->marked < data->held) && (data->type == type || type == IT_ANYTHING))
7064 {
7065 if (type != IT_ANYTHING)
7066 data->marked++;
7067 c++;
7068 if (c == amount)
7069 return true;
7070 }
7071 }
7072 return false;
7073 }
7074
ingName(const std::vector<IngredientData * > & list,const std::string & name,int amount=1)7075 bool ingName(const std::vector<IngredientData*> &list, const std::string &name, int amount=1)
7076 {
7077 int c = 0;
7078 for (int i = 0; i < list.size(); i++)
7079 {
7080 IngredientData *data = list[i];
7081 if ((data->marked < data->held) && (nocasecmp(data->name, name)==0))//data->name == name)
7082 {
7083 data->marked++;
7084 c++;
7085 if (c == amount)
7086 return true;
7087 }
7088 }
7089 return false;
7090 }
7091
7092 const int numTreasures = 16*2;
7093
onPrevTreasurePage()7094 void Game::onPrevTreasurePage()
7095 {
7096 if (currentTreasurePage > 0)
7097 {
7098 dsq->sound->playSfx("menu-switch", 0.5);
7099 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7100
7101 currentTreasurePage--;
7102 refreshTreasureSlots();
7103 }
7104 else
7105 {
7106 if (numTreasures > 0)
7107 {
7108 dsq->sound->playSfx("menu-switch", 0.5);
7109 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7110
7111 currentTreasurePage = ((numTreasures-1)/treasurePageSize);
7112 refreshTreasureSlots();
7113 }
7114 }
7115 }
7116
onNextTreasurePage()7117 void Game::onNextTreasurePage()
7118 {
7119 if ((currentTreasurePage+1)*treasurePageSize < numTreasures)
7120 {
7121 dsq->sound->playSfx("menu-switch", 0.5);
7122 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7123
7124 currentTreasurePage++;
7125 refreshTreasureSlots();
7126 }
7127 else
7128 {
7129 if (currentTreasurePage != 0)
7130 {
7131 dsq->sound->playSfx("menu-switch", 0.5);
7132 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7133
7134 currentTreasurePage = 0;
7135 refreshTreasureSlots();
7136 }
7137 }
7138 }
7139
onPrevFoodPage()7140 void Game::onPrevFoodPage()
7141 {
7142 int lastFoodPage = currentFoodPage;
7143 if (currentFoodPage > 0)
7144 {
7145 currentFoodPage--;
7146 refreshFoodSlots(false);
7147 }
7148 else
7149 {
7150 if (dsq->continuity.hasIngredients())
7151 {
7152 currentFoodPage = ((dsq->continuity.ingredientCount()-1)/foodPageSize);
7153 refreshFoodSlots(false);
7154 }
7155 }
7156
7157 std::ostringstream os;
7158 os << "food page: " << currentFoodPage;
7159 debugLog(os.str());
7160
7161 if (currentFoodPage != lastFoodPage)
7162 {
7163 dsq->sound->playSfx("menu-switch", 0.5);
7164 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7165 }
7166 }
7167
onNextFoodPage()7168 void Game::onNextFoodPage()
7169 {
7170 int lastFoodPage = currentFoodPage;
7171 if ((currentFoodPage+1)*foodPageSize < dsq->continuity.ingredientCount())
7172 {
7173 currentFoodPage++;
7174 refreshFoodSlots(false);
7175 }
7176 else
7177 {
7178 if (currentFoodPage != 0)
7179 {
7180 currentFoodPage = 0;
7181 refreshFoodSlots(false);
7182 }
7183 }
7184
7185 if (currentFoodPage != lastFoodPage)
7186 {
7187 dsq->sound->playSfx("menu-switch", 0.5);
7188 dsq->spawnParticleEffect("menu-switch", worldLeftCenter, 0, 0, LR_HUD3, 1);
7189 }
7190 }
7191
onUseTreasure()7192 void Game::onUseTreasure()
7193 {
7194 debugLog("Use Treasure!");
7195
7196 if (selectedTreasureFlag != -1)
7197 {
7198 onUseTreasure(selectedTreasureFlag);
7199 }
7200 }
7201
onUseTreasure(int flag)7202 void Game::onUseTreasure(int flag)
7203 {
7204 if(dsq->mod.isActive())
7205 dsq->runScriptNum(dsq->mod.getPath() + "scripts/menu-treasures.lua", "useTreasure", flag);
7206 else
7207 dsq->runScriptNum("scripts/global/menu-treasures.lua", "useTreasure", flag);
7208 }
7209
findRecipe(const std::vector<IngredientData * > & list)7210 Recipe *Game::findRecipe(const std::vector<IngredientData*> &list)
7211 {
7212 if (list.size() < 2) return 0;
7213
7214 // there will be a number of types and a number of names
7215 // the types and names DO NOT overlap
7216 int rc = 0;
7217 Recipe *r = 0;
7218 Recipe *tr = 0;
7219 int q = 0, q2 = 0;
7220 for ( rc = 0; rc < dsq->continuity.recipes.size(); rc++)
7221 {
7222 for (int i = 0; i < list.size(); i++) list[i]->marked = 0;
7223
7224 tr = 0;
7225 r = &dsq->continuity.recipes[rc];
7226 tr = r;
7227 q = 0;
7228
7229 // get the amount of ingredients provided by the player
7230 int listAmount = list.size();
7231
7232 // get the amount of ingredients required
7233 int recipeAmount = 0;
7234
7235 for (int i = 0; i < r->types.size(); i++)
7236 recipeAmount += r->types[i].amount;
7237
7238 for (int i = 0; i < r->names.size(); i++)
7239 recipeAmount += r->names[i].amount;
7240
7241 if (listAmount != recipeAmount)
7242 continue;
7243
7244 for (int c = 0; c < r->types.size(); c++)
7245 {
7246 RecipeType *t = &r->types[c];
7247 if (ingType(list, t->type, t->amount))
7248 q++;
7249 else
7250 break;
7251 }
7252
7253 /*
7254 // if all the types are checked
7255 // AND there are no names to check
7256 // then you found it!
7257 if (q == r->types.size() && q > 0 && r->names.empty())
7258 {
7259 return tr;
7260 }
7261 */
7262
7263 // this check is _kinda_ unnecessary... but we'll see
7264 if (q == r->types.size())
7265 {
7266 q2 = 0;
7267 for (int c = 0; c < r->names.size(); c++)
7268 {
7269 RecipeName *n = &r->names[c];
7270 if (ingName(list, n->name, n->amount))
7271 q2++;
7272 else
7273 break;
7274 }
7275 if (q2 == r->names.size())
7276 {
7277 return r;
7278 }
7279 /*
7280 // if there were actually types to check
7281 // and they were checked successfully
7282 // (being in this section of code implies that there were no types OR there was a successful full check)
7283 else if (q>0 && tr)
7284 {
7285 // return the ingredient we found in types
7286
7287 // but this is kind of silly.
7288 // would make more sense to return earlier
7289 return tr;
7290 }
7291 */
7292 }
7293 }
7294
7295 for (int i = 0; i < list.size(); i++) list[i]->marked = 0;
7296
7297 if (rc == dsq->continuity.recipes.size())
7298 {
7299 /*
7300 data = dsq->continuity.getIngredientByName("SeaLoaf");
7301 if (data)
7302 {
7303 dsq->continuity.pickupIngredient(data);
7304 }
7305 */
7306 }
7307
7308 return 0;
7309 }
7310
updateCookList()7311 void Game::updateCookList()
7312 {
7313 cookList.clear();
7314 for (int i = 0; i < foodHolders.size(); i++)
7315 {
7316 IngredientData *ing = foodHolders[i]->getIngredient();
7317 if (!foodHolders[i]->isTrash() && ing)
7318 {
7319 std::ostringstream os;
7320 os << "cooklist: " << ing->name;
7321 debugLog(os.str());
7322 cookList.push_back(ing);
7323 }
7324 }
7325 }
7326
onRecipes()7327 void Game::onRecipes()
7328 {
7329 if (foodMenu)
7330 {
7331 toggleRecipeList(!recipeMenu.on);
7332 }
7333 }
7334
onKeyConfig()7335 void Game::onKeyConfig()
7336 {
7337 dsq->screenTransition->capture();
7338 toggleKeyConfigMenu(true);
7339 dsq->screenTransition->transition(MENUPAGETRANSTIME);
7340 }
7341
7342 #define DEBUG_COOK
7343
onCook()7344 void Game::onCook()
7345 {
7346 if (recipeMenu.on) return;
7347 if (cookDelay > 0) return;
7348
7349 debugLog("Cook!");
7350
7351 //std::vector<IngredientData*> list;
7352 updateCookList();
7353
7354 if (cookList.size() < 2 || recipeMenu.on) return;
7355
7356 AquariaGuiElement::canDirMoveGlobal = false;
7357
7358 cookDelay = 0.4;
7359
7360 bool cooked = false;
7361
7362 isCooking = true;
7363
7364 IngredientData *data=0;
7365 Recipe *r = findRecipe(cookList);
7366
7367 if (r)
7368 data = dsq->continuity.getIngredientDataByName(r->result);
7369 else if(cookingScript)
7370 {
7371 const char *p1 = cookList[0]->name.c_str();
7372 const char *p2 = cookList[1]->name.c_str();
7373 const char *p3 = cookList.size() >= 3 ? cookList[2]->name.c_str() : "";
7374 std::string ingname;
7375 if(cookingScript->call("cookFailure", p1, p2, p3, &ingname))
7376 {
7377 if(ingname.length())
7378 data = dsq->continuity.getIngredientDataByName(ingname);
7379 if(!data)
7380 goto endcook;
7381 }
7382 }
7383
7384 if(!data)
7385 {
7386 dsq->sound->playSfx("Denied");
7387 data = dsq->continuity.getIngredientDataByName("SeaLoaf");
7388
7389 bool tooMany = data && dsq->continuity.isIngredientFull(data);
7390
7391 if (!tooMany)
7392 {
7393 int f = dsq->continuity.getFlag(FLAG_SEALOAFANNOYANCE);
7394 f++;
7395 if (f >= 3)
7396 {
7397 dsq->voiceInterupt("naija_sealoaf");
7398 f = 0;
7399 }
7400 dsq->continuity.setFlag(FLAG_SEALOAFANNOYANCE, f);
7401 }
7402 }
7403
7404 if (data)
7405 {
7406 cooked = !dsq->continuity.isIngredientFull(data);
7407 }
7408
7409 if (cooked)
7410 {
7411 debugLog("Cooked something!");
7412
7413 // do animationy stuff.
7414
7415 core->mouse.buttonsEnabled = false;
7416
7417 bool longAnim = true;
7418 int cooks = dsq->continuity.getFlag(FLAG_COOKS);
7419
7420 if (cooks >= 4)
7421 longAnim = false;
7422
7423 for (int i = foodHolders.size()-1; i >= 0; i--)
7424 if (foodHolders[i]->alpha.x > 0 && !foodHolders[i]->isEmpty() && !foodHolders[i]->isTrash())
7425 foodHolders[i]->animateLid(true, longAnim);
7426
7427 //dsq->main(0.2);
7428
7429
7430 if (longAnim)
7431 {
7432 float ft = 0.8;
7433 float nt = 0.1;
7434 float nt2 = 0.2;
7435 void *handle = NULL;
7436
7437 /*
7438 if (!longAnim)
7439 {
7440 float factor = 0.3;
7441 ft *= factor;
7442 nt *= factor;
7443 nt2 *= factor;
7444 }
7445 */
7446
7447 PlaySfx note1;
7448 note1.name = getNoteName(0);
7449 PlaySfx note2;
7450 note2.name = getNoteName(4);
7451 PlaySfx note3;
7452 note3.name = getNoteName(3);
7453
7454 handle = dsq->sound->playSfx(note1);
7455 dsq->main(nt2);
7456 dsq->sound->fadeSfx(handle, SFT_OUT, ft);
7457 dsq->main(nt);
7458
7459 handle = dsq->sound->playSfx(note2);
7460 dsq->main(nt2);
7461 dsq->sound->fadeSfx(handle, SFT_OUT, ft);
7462 dsq->main(nt);
7463
7464 handle = dsq->sound->playSfx(note3);
7465 dsq->main(nt2);
7466 dsq->sound->fadeSfx(handle, SFT_OUT, ft);
7467 dsq->main(nt);
7468 }
7469
7470 dsq->sound->playSfx("boil");
7471
7472 for (int i = 0; i < foodHolders.size(); i++)
7473 {
7474 if (!foodHolders[i]->isEmpty())
7475 dsq->spawnParticleEffect("cook-ingredient", foodHolders[i]->getWorldPosition(), 0, 0, LR_HUD3, 1);
7476 }
7477
7478 if (longAnim)
7479 dsq->main(0.5);
7480 else
7481 dsq->main(0.2);
7482
7483 bool haveLeftovers = true;
7484 for (int i = 0; i < foodHolders.size(); i++)
7485 {
7486 if (!foodHolders[i]->isEmpty()) {
7487 IngredientData *ing = foodHolders[i]->getIngredient();
7488 if (!ing || ing->amount < ing->held)
7489 {
7490 haveLeftovers = false;
7491 break;
7492 }
7493 }
7494 }
7495 for (int i = 0; i < foodHolders.size(); i++)
7496 {
7497 IngredientData *ing = foodHolders[i]->getIngredient();
7498 if (ing)
7499 {
7500 ing->amount--;
7501 }
7502
7503 if (!haveLeftovers)
7504 {
7505 foodHolders[i]->setIngredient(0, false);
7506 }
7507 }
7508
7509 dsq->sound->playSfx("Cook");
7510
7511 for (int i = 0; i < foodHolders.size(); i++)
7512 if (foodHolders[i]->alpha.x > 0 && !foodHolders[i]->isTrash())
7513 foodHolders[i]->animateLid(false);
7514
7515 dsq->spawnParticleEffect("cook-food", Vector(575,250), 0, 0, LR_HUD3, 1);
7516
7517 if (longAnim)
7518 dsq->main(0.5);
7519 else
7520 dsq->main(0.2);
7521
7522 if (data)
7523 {
7524 float t = 3;
7525 std::string n = "Ingredients/" + data->gfx;
7526 //Quad *e = new Quad();
7527
7528 showRecipe->setTexture(n);
7529 showRecipe->scale = Vector(0.5, 0.5);
7530 showRecipe->scale.interpolateTo(Vector(1.2, 1.2), t);
7531 showRecipe->alpha.ensureData();
7532 showRecipe->alpha.data->path.clear();
7533 showRecipe->alpha.data->path.addPathNode(0, 0);
7534 showRecipe->alpha.data->path.addPathNode(1, 0.1);
7535 showRecipe->alpha.data->path.addPathNode(1, 0.6);
7536 showRecipe->alpha.data->path.addPathNode(0, 1);
7537 showRecipe->alpha.startPath(t);
7538 }
7539
7540 dsq->continuity.pickupIngredient(data, 1);
7541
7542 dsq->continuity.removeEmptyIngredients();
7543
7544 dsq->main(0.5);
7545
7546 dsq->continuity.setFlag(FLAG_COOKS, dsq->continuity.getFlag(FLAG_COOKS)+1);
7547
7548 if (r)
7549 {
7550 dsq->continuity.learnRecipe(r);
7551 if (haveLeftovers)
7552 updatePreviewRecipe();
7553 }
7554
7555 core->mouse.buttonsEnabled = true;
7556 }
7557 else
7558 {
7559 dsq->sound->playSfx("Denied");
7560 dsq->centerMessage(dsq->continuity.stringBank.get(27));
7561 }
7562 refreshFoodSlots(true);
7563
7564 endcook:
7565
7566 AquariaGuiElement::canDirMoveGlobal = true;
7567
7568 isCooking = false;
7569 }
7570
overrideZoom(float sz,float t)7571 void Game::overrideZoom(float sz, float t)
7572 {
7573 if (sz == 0)
7574 {
7575 dsq->game->toggleOverrideZoom(false);
7576 }
7577 else
7578 {
7579 dsq->game->toggleOverrideZoom(true);
7580 dsq->globalScale.stop();
7581 dsq->globalScale.interpolateTo(Vector(sz, sz), t);
7582 dsq->globalScaleChanged();
7583 }
7584 }
7585
getFoodSlotFromIndex()7586 FoodSlot* getFoodSlotFromIndex()
7587 {
7588 for (int i = 0; i < dsq->game->foodSlots.size(); i++)
7589 {
7590 if (dsq->game->foodSlots[i]->slot == FoodSlot::foodSlotIndex)
7591 {
7592 return dsq->game->foodSlots[i];
7593 }
7594 }
7595 return 0;
7596 }
7597
onLips()7598 void Game::onLips()
7599 {
7600 if (!foodMenu)
7601 {
7602 if (dsq->lastVoiceFile.find("NAIJA_SONG_") != std::string::npos)
7603 {
7604 dsq->stopVoice();
7605 }
7606 }
7607 }
7608
7609 const float hintTransTime = 0.5;
7610
clearControlHint()7611 void Game::clearControlHint()
7612 {
7613 if (!controlHint_ignoreClear)
7614 {
7615 controlHintTimer = 0;
7616
7617 if (controlHint_bg)
7618 {
7619 controlHint_mouseLeft->alpha.interpolateTo(0, hintTransTime);
7620 controlHint_mouseRight->alpha.interpolateTo(0, hintTransTime);
7621 controlHint_mouseMiddle->alpha.interpolateTo(0, hintTransTime);
7622 controlHint_mouseBody->alpha.interpolateTo(0, hintTransTime);
7623 controlHint_text->alpha.interpolateTo(0, hintTransTime);
7624 controlHint_bg->alpha.interpolateTo(0, hintTransTime);
7625 controlHint_image->alpha.interpolateTo(0, hintTransTime);
7626 }
7627
7628 for (int i = 0; i < controlHintNotes.size(); i++)
7629 {
7630 controlHintNotes[i]->alpha.interpolateTo(0, hintTransTime);
7631 }
7632 controlHintNotes.clear();
7633 }
7634 }
7635
getWaterLevel()7636 float Game::getWaterLevel()
7637 {
7638 return waterLevel.x;
7639 }
7640
setControlHint(const std::string & h,bool left,bool right,bool middle,float time,std::string image,bool ignoreClear,int songType,float scale)7641 void Game::setControlHint(const std::string &h, bool left, bool right, bool middle, float time, std::string image, bool ignoreClear, int songType, float scale)
7642 {
7643 if (!h.empty())
7644 dsq->sound->playSfx("controlhint");
7645
7646 controlHint_ignoreClear = false;
7647 clearControlHint();
7648 std::string hint = h;
7649
7650 controlHintTimer = time;
7651
7652 if (core->flipMouseButtons)
7653 {
7654 if (h.find("Left")!=std::string::npos && h.find("Right")==std::string::npos)
7655 {
7656 std::string sought = "Left";
7657 std::string replacement = "Right";
7658 hint.replace(hint.find(sought), sought.size(), replacement);
7659 }
7660 else if (h.find("Left")==std::string::npos && h.find("Right")!=std::string::npos)
7661 {
7662 std::string sought = "Right";
7663 std::string replacement = "Left";
7664 hint.replace(hint.find(sought), sought.size(), replacement);
7665 }
7666 std::swap(left, right);
7667 }
7668
7669 std::ostringstream os;
7670 os << "set control hint: (" << hint << ", " << left << ", " << right << ", " << middle << " t: " << time << " )";
7671 debugLog(os.str());
7672
7673 if (songType > 0)
7674 {
7675 //Song *song = getSongByIndex(num);
7676 Song *song = dsq->continuity.getSongByIndex(songType);
7677 controlHintNotes.clear();
7678
7679 Vector p = controlHint_mouseLeft->position + Vector(-100,0);
7680
7681 char sbuf[32];
7682 sprintf(sbuf, "song/songslot-%d", dsq->continuity.getSongSlotByType(songType));
7683 Quad *q = new Quad(sbuf, p);
7684 q->followCamera = 1;
7685 q->scale = Vector(0.7, 0.7);
7686 q->alpha = 0;
7687 addRenderObject(q, controlHint_bg->layer);
7688 controlHintNotes.push_back(q);
7689
7690 p += Vector(100, 0);
7691
7692 for (int i = 0; i < song->notes.size(); i++)
7693 {
7694 int note = song->notes[i];
7695
7696 sprintf(sbuf, "song/notebutton-%d", note);
7697 Quad *q = new Quad(sbuf, p);
7698 q->color = dsq->getNoteColor(note)*0.5f + Vector(1, 1, 1)*0.5f;
7699 q->followCamera = 1;
7700 q->scale = Vector(1.0, 1.0);
7701 q->alpha = 0;
7702
7703 if (i % 2)
7704 q->offset = Vector(0, -10);
7705 else
7706 q->offset = Vector(0, 10);
7707
7708 addRenderObject(q, controlHint_bg->layer);
7709
7710 controlHintNotes.push_back(q);
7711
7712 p += Vector(40, 0);
7713 }
7714 }
7715
7716 float alphaOn = 0.8, alphaOff = 0.5;
7717 controlHint_bg->alpha.interpolateTo(1, hintTransTime);
7718 controlHint_bg->scale = Vector(1,1);
7719 //controlHint_bg->scale = Vector(0,1);
7720 //controlHint_bg->scale.interpolateTo(Vector(1,1), hintTransTime);
7721 controlHint_text->setText(hint);
7722 controlHint_text->alpha.interpolateTo(1, hintTransTime);
7723
7724 if (!image.empty())
7725 {
7726 controlHint_image->setTexture(image);
7727 controlHint_image->alpha.interpolateTo(1, hintTransTime);
7728 controlHint_image->scale = Vector(scale, scale);
7729 //controlHint_image->scale = Vector(0.5, 0.5);
7730 }
7731 else
7732 {
7733 controlHint_image->alpha.interpolateTo(0, hintTransTime);
7734 }
7735
7736
7737 controlHint_text->position.x = 400 - controlHint_text->getSetWidth()/2 + 25;
7738 //400 - controlHint_bg->getWidth()/2 + 25;
7739 controlHint_text->setAlign(ALIGN_LEFT);
7740
7741 if (!left && !right && !middle)
7742 {
7743 controlHint_mouseRight->alpha.interpolateTo(0, hintTransTime);
7744 controlHint_mouseLeft->alpha.interpolateTo(0, hintTransTime);
7745 controlHint_mouseMiddle->alpha.interpolateTo(0, hintTransTime);
7746 if (image.empty() && controlHintNotes.empty())
7747 {
7748 controlHint_text->position.y = 470;
7749 }
7750 else
7751 {
7752 controlHint_text->position.y = 520;
7753 controlHint_text->position.x = 400;
7754 controlHint_text->setAlign(ALIGN_CENTER);
7755 }
7756 }
7757 else
7758 {
7759 controlHint_text->position.y = 520;
7760 controlHint_text->position.x = 400;
7761 controlHint_text->setAlign(ALIGN_CENTER);
7762 if (left)
7763 controlHint_mouseLeft->alpha.interpolateTo(alphaOn, hintTransTime);
7764 else
7765 controlHint_mouseLeft->alpha.interpolateTo(alphaOff, hintTransTime);
7766
7767 if (right)
7768 controlHint_mouseRight->alpha.interpolateTo(alphaOn, hintTransTime);
7769 else
7770 controlHint_mouseRight->alpha.interpolateTo(alphaOff, hintTransTime);
7771
7772 if (middle)
7773 controlHint_mouseMiddle->alpha.interpolateTo(alphaOn, hintTransTime);
7774 else
7775 controlHint_mouseMiddle->alpha.interpolateTo(alphaOff, hintTransTime);
7776 controlHint_mouseBody->alpha.interpolateTo(0.5, hintTransTime);
7777 }
7778
7779 for (int i = 0; i < controlHintNotes.size(); i++)
7780 {
7781 controlHintNotes[i]->alpha.interpolateTo(alphaOn, hintTransTime);
7782 }
7783
7784 controlHint_ignoreClear = ignoreClear;
7785
7786
7787 controlHint_shine->alpha.ensureData();
7788 controlHint_shine->alpha.data->path.clear();
7789 controlHint_shine->alpha.data->path.addPathNode(0.001, 0.0);
7790 controlHint_shine->alpha.data->path.addPathNode(1.000, 0.3);
7791 controlHint_shine->alpha.data->path.addPathNode(0.001, 1.0);
7792 controlHint_shine->alpha.startPath(0.4);
7793 }
7794
onFlipTest()7795 void Game::onFlipTest()
7796 {
7797 flipSceneVertical(14960);
7798 }
7799
appendFileToString(std::string & string,const std::string & file)7800 void appendFileToString(std::string &string, const std::string &file)
7801 {
7802 InStream inf(file.c_str());
7803
7804 if (inf.is_open())
7805 {
7806 while (!inf.eof())
7807 {
7808 std::string read;
7809 std::getline(inf, read);
7810 #if BBGE_BUILD_UNIX
7811 read = stripEndlineForUnix(read);
7812 #endif
7813 read = dsq->user.control.actionSet.insertInputIntoString(read);
7814 string += read + "\n";
7815 }
7816 }
7817
7818 inf.close();
7819 }
7820
onToggleHelpScreen()7821 void Game::onToggleHelpScreen()
7822 {
7823 if (inHelpScreen)
7824 toggleHelpScreen(false);
7825 else if (core->isStateJumpPending())
7826 return;
7827 else
7828 {
7829 if (worldMapRender->isOn())
7830 {
7831 toggleHelpScreen(true, "[World Map]");
7832 }
7833 else if (currentMenuPage == MENUPAGE_FOOD)
7834 {
7835 toggleHelpScreen(true, "[Food]");
7836 }
7837 else if (currentMenuPage == MENUPAGE_TREASURES)
7838 {
7839 toggleHelpScreen(true, "[Treasures]");
7840 }
7841 /*
7842 else if (currentMenuPage == MENUPAGE_SONGS)
7843 {
7844 toggleHelpScreen(true, "[Singing]");
7845 }
7846 */
7847 else if (currentMenuPage == MENUPAGE_PETS)
7848 {
7849 toggleHelpScreen(true, "[Pets]");
7850 }
7851 else
7852 {
7853 toggleHelpScreen(true);
7854 }
7855 }
7856 }
7857
toggleHelpScreen(bool on,const std::string & label)7858 void Game::toggleHelpScreen(bool on, const std::string &label)
7859 {
7860 if (dsq->game->isSceneEditorActive()) return;
7861
7862 if (inHelpScreen == on) return;
7863 if (core->getShiftState()) return;
7864 if (dsq->screenTransition->isGoing()) return;
7865 if (dsq->isNested()) return;
7866 if (dsq->saveSlotMode != SSM_NONE) return;
7867
7868 if (on)
7869 {
7870 AquariaGuiElement::currentGuiInputLevel = 100;
7871 dsq->screenTransition->capture();
7872
7873 helpWasPaused = isPaused();
7874 togglePause(true);
7875
7876 std::string data;
7877
7878 // These say "Mac" but we use them on Linux, too.
7879 #if defined(BBGE_BUILD_UNIX)
7880 std::string fname = localisePath("data/help_header_mac.txt");
7881 appendFileToString(data, fname);
7882 #else
7883 std::string fname = localisePath("data/help_header.txt");
7884 appendFileToString(data, fname);
7885 #endif
7886 if (dsq->continuity.hasSong(SONG_BIND)) {
7887 fname = localisePath("data/help_bindsong.txt");
7888 appendFileToString(data, fname);
7889 }
7890 if (dsq->continuity.hasSong(SONG_ENERGYFORM)) {
7891 fname = localisePath("data/help_energyform.txt");
7892 appendFileToString(data, fname);
7893 }
7894 fname = localisePath("data/help_start.txt");
7895 appendFileToString(data, fname);
7896
7897 // These say "Mac" but we use them on Linux, too.
7898 #if defined(BBGE_BUILD_UNIX)
7899 fname = localisePath("data/help_end_mac.txt");
7900 appendFileToString(data, fname);
7901 #else
7902 fname = localisePath("data/help_end.txt");
7903 appendFileToString(data, fname);
7904 #endif
7905
7906 // !!! FIXME: this is such a hack.
7907 data += "\n\n" + dsq->continuity.stringBank.get(2032) + "\n\n";
7908 dsq->continuity.statsAndAchievements->appendStringData(data);
7909
7910 helpBG = new Quad;
7911 //helpBG->color = 0;
7912 helpBG->setTexture("brick");
7913 helpBG->repeatTextureToFill(true);
7914 helpBG->repeatToFillScale = Vector(2, 2);
7915 //helpBG->alphaMod = 0.75;
7916 helpBG->autoWidth = AUTO_VIRTUALWIDTH;
7917 helpBG->autoHeight = AUTO_VIRTUALHEIGHT;
7918 helpBG->position = Vector(400,300);
7919 helpBG->followCamera = 1;
7920 addRenderObject(helpBG, LR_HELP);
7921
7922 helpBG2 = new Quad;
7923 helpBG2->color = 0;
7924 helpBG2->alphaMod = 0.5;
7925 helpBG2->setWidth(620);
7926 helpBG2->autoHeight = AUTO_VIRTUALHEIGHT;
7927 helpBG2->position = Vector(400,300);
7928 helpBG2->followCamera = 1;
7929 addRenderObject(helpBG2, LR_HELP);
7930
7931 helpText = new TTFText(&dsq->fontArialSmall);
7932 //test->setAlign(ALIGN_CENTER);
7933 helpText->setWidth(600);
7934 helpText->setText(data);
7935 //test->setAlign(ALIGN_CENTER);
7936 helpText->cull = false;
7937 helpText->followCamera = 1;
7938 helpText->position = Vector(100, 20);
7939 if (!label.empty())
7940 {
7941 int line = helpText->findLine(label);
7942 helpText->offset.interpolateTo(Vector(0, -helpText->getLineHeight()*line), -1200);
7943 }
7944
7945 //helpText->offset.interpolateTo(Vector(0, -400), 4, -1, 1);
7946 //test->position = Vector(400,300);
7947 addRenderObject(helpText, LR_HELP);
7948
7949 helpUp = new AquariaMenuItem;
7950 helpUp->useQuad("Gui/arrow-left");
7951 helpUp->useSound("click");
7952 helpUp->useGlow("particles/glow", 64, 32);
7953 helpUp->position = Vector(50, 40);
7954 helpUp->followCamera = 1;
7955 helpUp->rotation.z = 90;
7956 helpUp->event.set(MakeFunctionEvent(Game, onHelpUp));
7957 helpUp->scale = Vector(0.6, 0.6);
7958 helpUp->guiInputLevel = 100;
7959 addRenderObject(helpUp, LR_HELP);
7960
7961 helpDown = new AquariaMenuItem;
7962 helpDown->useQuad("Gui/arrow-right");
7963 helpDown->useSound("click");
7964 helpDown->useGlow("particles/glow", 64, 32);
7965 helpDown->position = Vector(50, 600-40);
7966 helpDown->followCamera = 1;
7967 helpDown->rotation.z = 90;
7968 helpDown->event.set(MakeFunctionEvent(Game, onHelpDown));
7969 helpDown->scale = Vector(0.6, 0.6);
7970 helpDown->guiInputLevel = 100;
7971 addRenderObject(helpDown, LR_HELP);
7972
7973 helpCancel = new AquariaMenuItem;
7974 helpCancel->useQuad("Gui/cancel");
7975 helpCancel->useSound("click");
7976 helpCancel->useGlow("particles/glow", 128, 40);
7977 helpCancel->position = Vector(750, 600-20);
7978 helpCancel->followCamera = 1;
7979 //helpCancel->rotation.z = 90;
7980 helpCancel->event.set(MakeFunctionEvent(Game, toggleHelpScreen));
7981 helpCancel->scale = Vector(0.9, 0.9);
7982 helpCancel->guiInputLevel = 100;
7983 addRenderObject(helpCancel, LR_HELP);
7984
7985 for (int i = 0; i < LR_HELP; i++)
7986 {
7987 core->getRenderObjectLayer(i)->visible = false;
7988 }
7989
7990 core->resetTimer();
7991
7992 dsq->screenTransition->transition(MENUPAGETRANSTIME);
7993 }
7994 else
7995 {
7996 if (!helpWasPaused)
7997 togglePause(false);
7998 dsq->screenTransition->capture();
7999 if (helpText)
8000 {
8001 helpText->alpha = 0;
8002 helpText->setLife(1);
8003 helpText->setDecayRate(1000);
8004 helpText = 0;
8005 }
8006 if (helpBG)
8007 {
8008 helpBG->alpha = 0;
8009 helpBG->setLife(1);
8010 helpBG->setDecayRate(1000);
8011 helpBG = 0;
8012 }
8013 if (helpBG2)
8014 {
8015 helpBG2->alpha = 0;
8016 helpBG2->setLife(1);
8017 helpBG2->setDecayRate(1000);
8018 helpBG2 = 0;
8019 }
8020 if (helpUp)
8021 {
8022 helpUp->alpha = 0;
8023 helpUp->setLife(1);
8024 helpUp->setDecayRate(1000);
8025 helpUp = 0;
8026 }
8027 if (helpDown)
8028 {
8029 helpDown->alpha = 0;
8030 helpDown->setLife(1);
8031 helpDown->setDecayRate(1000);
8032 helpDown = 0;
8033 }
8034 if (helpCancel)
8035 {
8036 helpCancel->alpha = 0;
8037 helpCancel->setLife(1);
8038 helpCancel->setDecayRate(1000);
8039 helpCancel = 0;
8040 }
8041
8042 for (int i = 0; i < LR_HELP; i++)
8043 {
8044 core->getRenderObjectLayer(i)->visible = true;
8045 }
8046 dsq->applyParallaxUserSettings();
8047
8048 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8049
8050
8051 AquariaGuiElement::currentGuiInputLevel = 0;
8052 }
8053
8054 inHelpScreen = on;
8055 }
updateMusic()8056 bool Game::updateMusic()
8057 {
8058 std::string musicToPlay = this->musicToPlay;
8059 if (!overrideMusic.empty())
8060 {
8061 musicToPlay = overrideMusic;
8062 }
8063
8064 if (!musicToPlay.empty())
8065 {
8066 if (musicToPlay == "none")
8067 core->sound->fadeMusic(SFT_OUT, 1);
8068 else
8069 {
8070 bool play = true;
8071 /*
8072 std::string originalFile = musicToPlay;
8073 std::string file = originalFile;
8074
8075 if (!exists(file, false) && file.find('.') == std::string::npos)
8076 {
8077 file = originalFile + ".ogg";
8078 if (!exists(file, false))
8079 {
8080 file = originalFile + ".mp3";
8081 if (!exists(file, false))
8082 {
8083 errorLog ("music file not found [" + originalFile + "]");
8084 play = false;
8085 }
8086 }
8087 }
8088 */
8089 if (play)
8090 {
8091 /*
8092 if (core->sound->isStreamingMusic())
8093 core->sound->crossfadeOutMusic(1);
8094 */
8095 return core->sound->playMusic(musicToPlay, SLT_LOOP, SFT_CROSS, 1, SCT_ISNOTPLAYING);
8096 }
8097 }
8098 }
8099 else
8100 {
8101 core->sound->fadeMusic(SFT_OUT, 1);
8102 }
8103 return false;
8104 }
8105
onPressEscape()8106 void Game::onPressEscape()
8107 {
8108 if (dsq->isInCutscene())
8109 {
8110 // do nothing (moved to dsq::
8111 }
8112 else
8113 {
8114 if (inHelpScreen)
8115 {
8116 toggleHelpScreen(false);
8117 return;
8118 }
8119 if (dsq->game->worldMapRender->isOn() && !dsq->isNested())
8120 {
8121 dsq->game->worldMapRender->toggle(false);
8122 return;
8123 }
8124 if (dsq->game->isInGameMenu())
8125 {
8126 if (!AquariaKeyConfig::waitingForInput)
8127 {
8128 if (dsq->game->menuOpenTimer > 0.5f)
8129 {
8130 if (optionsMenu || keyConfigMenu)
8131 onOptionsCancel();
8132 else
8133 action(ACTION_TOGGLEMENU, 0); // hide menu
8134 }
8135 }
8136 return;
8137 }
8138
8139 if (!paused)
8140 {
8141 if (core->getNestedMains() == 1 && !core->isStateJumpPending())
8142 action(ACTION_TOGGLEMENU, 1); // show menu
8143 }
8144 else
8145 {
8146
8147 if (autoMap)
8148 {
8149 if (paused && autoMap->isOn())
8150 autoMap->toggle(false);
8151 }
8152 }
8153
8154
8155 if ((dsq->saveSlotMode != SSM_NONE || dsq->inModSelector) && core->isNested())
8156 {
8157 dsq->selectedSaveSlot = 0;
8158 core->quitNestedMain();
8159 }
8160 }
8161 }
8162
onDebugSave()8163 void Game::onDebugSave()
8164 {
8165 hideInGameMenu();
8166 clearControlHint();
8167 core->main(0.5);
8168 dsq->game->togglePause(true);
8169 dsq->doSaveSlotMenu(SSM_SAVE);
8170 dsq->game->togglePause(false);
8171 //dsq->continuity.saveFile(0);
8172 }
8173
onInGameMenuInventory()8174 void Game::onInGameMenuInventory()
8175 {
8176 }
8177
onInGameMenuSpellBook()8178 void Game::onInGameMenuSpellBook()
8179 {
8180 }
8181
onInGameMenuContinue()8182 void Game::onInGameMenuContinue()
8183 {
8184 hideInGameMenu();
8185 }
8186
onInGameMenuOptions()8187 void Game::onInGameMenuOptions()
8188 {
8189 }
8190
onInGameMenuSave()8191 void Game::onInGameMenuSave()
8192 {
8193 }
8194
onExitCheckYes()8195 void Game::onExitCheckYes()
8196 {
8197 dsq->sound->stopAllVoice();
8198 dsq->toggleCursor(0, 0.25);
8199 dsq->title();
8200 }
8201
onExitCheckNo()8202 void Game::onExitCheckNo()
8203 {
8204 hideInGameMenuExitCheck(true);
8205 }
8206
showInGameMenuExitCheck()8207 void Game::showInGameMenuExitCheck()
8208 {
8209 recipeMenu.toggle(false);
8210 inGameMenuExitState = 1;
8211 eYes->alpha.interpolateTo(1, 0.2);
8212 eNo->alpha.interpolateTo(1, 0.2);
8213 eAre->alpha.interpolateTo(1, 0.2);
8214
8215 eNo->setFocus(true);
8216 }
8217
hideInGameMenuExitCheck(bool refocus)8218 void Game::hideInGameMenuExitCheck(bool refocus)
8219 {
8220 inGameMenuExitState = 0;
8221 eYes->alpha.interpolateTo(0, 0.2);
8222 eNo->alpha.interpolateTo(0, 0.2);
8223 eAre->alpha.interpolateTo(0, 0.2);
8224
8225 if (refocus)
8226 ((AquariaMenuItem*)menu[1])->setFocus(true);
8227 }
8228
onInGameMenuExit()8229 void Game::onInGameMenuExit()
8230 {
8231 if (!dsq->user.demo.warpKeys || (core->getCtrlState() && core->getAltState()))
8232 {
8233 if (inGameMenuExitState == 0)
8234 {
8235 // show yes/no
8236 showInGameMenuExitCheck();
8237 }
8238 }
8239 }
8240
toggleDamageSprite(bool on)8241 void Game::toggleDamageSprite(bool on)
8242 {
8243 if (on)
8244 {
8245 damageSprite->alphaMod = 1;
8246 }
8247 else
8248 damageSprite->alphaMod = 0;
8249 }
8250
togglePause(bool v)8251 void Game::togglePause(bool v)
8252 {
8253 paused = v;
8254 if (paused)
8255 {
8256 dsq->cursorGlow->alpha = 0;
8257 dsq->cursorBlinker->alpha = 0;
8258 //dsq->overlay->alpha.interpolateTo(0.5, 0.5);
8259 }
8260 //core->particlesPaused = v;
8261 /*
8262 else
8263 dsq->overlay->alpha.interpolateTo(0, 0.5);
8264 */
8265 }
8266
isPaused()8267 bool Game::isPaused()
8268 {
8269 return paused;
8270 }
8271
playBurstSound(bool wallJump)8272 void Game::playBurstSound(bool wallJump)
8273 {
8274 int freqBase = 950;
8275 if (wallJump)
8276 freqBase += 100;
8277 sound->playSfx("Burst", 1);
8278 if (chance(50))
8279 {
8280 switch (dsq->continuity.form)
8281 {
8282 case FORM_BEAST:
8283 sound->playSfx("BeastBurst", (128+rand()%64)/256.0f);
8284 break;
8285 }
8286 }
8287 }
8288
collideCircleVsCircle(Entity * a,Entity * b)8289 bool Game::collideCircleVsCircle(Entity *a, Entity *b)
8290 {
8291 return (a->position - b->position).isLength2DIn(a->collideRadius + b->collideRadius);
8292 }
8293
collideHairVsCircle(Entity * a,int num,const Vector & pos2,float radius,float perc,int * colSegment)8294 bool Game::collideHairVsCircle(Entity *a, int num, const Vector &pos2, float radius, float perc, int *colSegment)
8295 {
8296 if (perc == 0)
8297 perc = 1;
8298 bool c = false;
8299 if (a && a->hair)
8300 {
8301 if (num == 0)
8302 num = a->hair->hairNodes.size();
8303 // HACK: minus 2
8304 for (int i = 0; i < num; i++)
8305 {
8306 // + a->hair->position
8307 c = ((a->hair->hairNodes[i].position) - pos2).isLength2DIn(a->hair->hairWidth*perc + radius);
8308 if (c)
8309 {
8310 if (colSegment)
8311 *colSegment = i;
8312 return true;
8313 }
8314 }
8315 }
8316 return c;
8317 }
8318
8319 // NOTE THIS FUNCTION ASSUMES THAT IF A BONE ISN'T AT FULL ALPHA (1.0) IT IS DISABLED
collideSkeletalVsCircle(Entity * skeletal,RenderObject * circle)8320 Bone *Game::collideSkeletalVsCircle(Entity *skeletal, RenderObject *circle)
8321 {
8322 return collideSkeletalVsCircle(skeletal, circle->position, circle->collideRadius);
8323 }
8324
collideSkeletalVsLine(Entity * skeletal,Vector start,Vector end,float radius)8325 Bone *Game::collideSkeletalVsLine(Entity *skeletal, Vector start, Vector end, float radius)
8326 {
8327 //float smallestDist = HUGE_VALF;
8328 Bone *closest = 0;
8329 for (int i = 0; i < skeletal->skeletalSprite.bones.size(); i++)
8330 {
8331 Bone *b = skeletal->skeletalSprite.bones[i];
8332 /*
8333 int checkRadius = sqr(radius+b->collisionMaskRadius);
8334 Vector bonePos = b->getWorldCollidePosition();
8335 float dist = (bonePos - pos).getSquaredLength2D();
8336 */
8337
8338 // MULTIPLE CIRCLES METHOD
8339 if (!b->collisionMask.empty() && b->alpha.x == 1 && b->renderQuad)
8340 {
8341 for (int i = 0; i < b->transformedCollisionMask.size(); i++)
8342 {
8343 if (isTouchingLine(start, end, b->transformedCollisionMask[i], radius+b->collideRadius))
8344 {
8345 closest = b;
8346 //smallestDist = dist;
8347 break;
8348 }
8349 }
8350 }
8351 if (closest != 0)
8352 {
8353 break;
8354 }
8355 /*
8356 // ONE CIRCLE PER BONE METHOD
8357 else if (b->collideRadius && b->alpha.x == 1)
8358 {
8359 if (dist < checkRadius)
8360 {
8361 if (dist < smallestDist)
8362 {
8363 closest = b;
8364 smallestDist = dist;
8365 }
8366 }
8367 }
8368 */
8369 }
8370 return closest;
8371 }
8372
collideCircleVsLine(RenderObject * r,Vector start,Vector end,float radius)8373 bool Game::collideCircleVsLine(RenderObject *r, Vector start, Vector end, float radius)
8374 {
8375 bool collision = false;
8376 if (isTouchingLine(start, end, r->position, radius+r->collideRadius, &lastCollidePosition))
8377 {
8378 collision = true;
8379 }
8380 return collision;
8381 }
8382
collideCircleVsLineAngle(RenderObject * r,float angle,float startLen,float endLen,float radius,Vector basePos)8383 bool Game::collideCircleVsLineAngle(RenderObject *r, float angle, float startLen, float endLen, float radius, Vector basePos)
8384 {
8385 bool collision = false;
8386 float rads = MathFunctions::toRadians(angle);
8387 float sinv = sinf(rads);
8388 float cosv = cosf(rads);
8389 Vector start=Vector(sinv,cosv)*startLen + basePos;
8390 Vector end=Vector(sinv,cosv)*endLen + basePos;
8391 if (isTouchingLine(start, end, r->position, radius+r->collideRadius, &lastCollidePosition))
8392 {
8393 collision = true;
8394 }
8395 if (shapeDebug)
8396 {
8397 shapeDebug->position = end;
8398 }
8399 return collision;
8400 }
8401
8402
collideSkeletalVsCircle(Entity * skeletal,Vector pos,float radius)8403 Bone *Game::collideSkeletalVsCircle(Entity *skeletal, Vector pos, float radius)
8404 {
8405 float smallestDist = HUGE_VALF;
8406 Bone *closest = 0;
8407 if (!(pos - skeletal->position).isLength2DIn(2000)) return 0;
8408 for (int i = 0; i < skeletal->skeletalSprite.bones.size(); i++)
8409 {
8410 Bone *b = skeletal->skeletalSprite.bones[i];
8411
8412 if (b->alpha.x == 1 && b->renderQuad)
8413 {
8414 float checkRadius = sqr(radius+b->collisionMaskRadius);
8415 Vector bonePos = b->getWorldCollidePosition();
8416 float dist = (bonePos - pos).getSquaredLength2D();
8417 // BOUND RECT METHOD
8418 if (!b->collisionRects.empty())
8419 {
8420 for (int i = 0; i < b->collisionRects.size(); i++)
8421 {
8422 b->collisionRects[i].isCoordinateInside(pos, radius);
8423 }
8424 }
8425 // MULTIPLE CIRCLES METHOD
8426 else if (!b->collisionMask.empty())
8427 {
8428 if (dist < checkRadius)
8429 {
8430 for (int i = 0; i < b->transformedCollisionMask.size(); i++)
8431 {
8432 if ((b->transformedCollisionMask[i] - pos).isLength2DIn(radius+b->collideRadius*skeletal->scale.x))
8433 {
8434 closest = b;
8435 smallestDist = dist;
8436 lastCollideMaskIndex = i;
8437 break;
8438 }
8439 }
8440 }
8441 }
8442 // ONE CIRCLE PER BONE METHOD
8443 else if (b->collideRadius)
8444 {
8445 if (dist < sqr(radius+b->collideRadius))
8446 {
8447 if (dist < smallestDist)
8448 {
8449 closest = b;
8450 smallestDist = dist;
8451 }
8452 }
8453 }
8454 }
8455 }
8456 return closest;
8457 }
8458
preLocalWarp(LocalWarpType localWarpType)8459 void Game::preLocalWarp(LocalWarpType localWarpType)
8460 {
8461 // won't work if you start the map inside a local warp area... but that doesn't happen much for collecting gems
8462 if (localWarpType == LOCALWARP_IN)
8463 {
8464 dsq->game->avatar->warpInLocal = dsq->game->avatar->position;
8465 }
8466 else if (localWarpType == LOCALWARP_OUT)
8467 {
8468 dsq->game->avatar->warpInLocal = Vector(0,0,0);
8469 }
8470
8471 dsq->screenTransition->capture();
8472 core->resetTimer();
8473 }
8474
postLocalWarp()8475 void Game::postLocalWarp()
8476 {
8477 if (dsq->game->li && dsq->continuity.hasLi())
8478 dsq->game->li->position = dsq->game->avatar->position;
8479 if (dsq->game->avatar->pullTarget)
8480 dsq->game->avatar->pullTarget->position = dsq->game->avatar->position;
8481 dsq->game->snapCam();
8482 dsq->screenTransition->transition(0.6);
8483
8484 }
8485
registerSporeDrop(const Vector & pos,int t)8486 void Game::registerSporeDrop(const Vector &pos, int t)
8487 {
8488 FOR_ENTITIES(i)
8489 {
8490 Entity *e = *i;
8491 if ((e->position - pos).isLength2DIn(1024))
8492 {
8493 e->sporesDropped(pos, t);
8494 }
8495 }
8496 }
8497
isEntityCollideWithShot(Entity * e,Shot * shot)8498 bool Game::isEntityCollideWithShot(Entity *e, Shot *shot)
8499 {
8500 if (!shot->isHitEnts() || shot->firer == e)
8501 {
8502 return false;
8503 }
8504 if (shot->checkDamageTarget)
8505 {
8506 if (!e->isDamageTarget(shot->getDamageType()))
8507 return false;
8508 }
8509 if (e->getEntityType() == ET_ENEMY)
8510 {
8511 if (shot->getDamageType() == DT_AVATAR_BITE)
8512 {
8513 Avatar::BittenEntities::iterator i;
8514 for (i = avatar->bittenEntities.begin(); i != avatar->bittenEntities.end(); i++)
8515 {
8516 if (e == (*i))
8517 {
8518 return false;
8519 }
8520 }
8521 return true;
8522 }
8523 }
8524 else if (e->getEntityType() == ET_AVATAR)
8525 {
8526 // this used to be stuff != ET_AVATAR.. but what else would do that
8527 return !dsq->game->isDamageTypeAvatar(shot->getDamageType()) && (!shot->firer || shot->firer->getEntityType() == ET_ENEMY);
8528 }
8529 else if (e->getEntityType() == ET_PET)
8530 {
8531 bool go = shot->firer != e;
8532 if (shot->firer && shot->firer->getEntityType() != ET_ENEMY)
8533 go = false;
8534 return go;
8535 }
8536
8537 return true;
8538 }
8539
handleShotCollisions(Entity * e,bool hasShield)8540 void Game::handleShotCollisions(Entity *e, bool hasShield)
8541 {
8542 BBGE_PROF(Game_handleShotCollisions);
8543 for (size_t i = 0; i < Shot::shots.size(); ++i)
8544 {
8545 Shot *shot = Shot::shots[i];
8546 if (shot->isActive() && isEntityCollideWithShot(e, shot) && (!hasShield || (!shot->shotData || !shot->shotData->ignoreShield)))
8547 {
8548 Vector collidePoint = e->position+e->offset;
8549 if (e->getNumTargetPoints()>0)
8550 {
8551 collidePoint = e->getTargetPoint(0);
8552 }
8553 if ((collidePoint - shot->position).isLength2DIn(shot->collideRadius + e->collideRadius))
8554 {
8555 lastCollidePosition = shot->position;
8556 shot->hitEntity(e,0);
8557 }
8558 }
8559 }
8560 }
8561
isDamageTypeAvatar(DamageType dt)8562 bool Game::isDamageTypeAvatar(DamageType dt)
8563 {
8564 return (dt >= DT_AVATAR && dt < DT_TOUCH);
8565 }
8566
isDamageTypeEnemy(DamageType dt)8567 bool Game::isDamageTypeEnemy(DamageType dt)
8568 {
8569 return (dt >= DT_ENEMY && dt < DT_AVATAR);
8570 }
8571
handleShotCollisionsSkeletal(Entity * e)8572 void Game::handleShotCollisionsSkeletal(Entity *e)
8573 {
8574 BBGE_PROF(Game_HSSKELETAL);
8575 for (size_t i = 0; i < Shot::shots.size(); ++i)
8576 {
8577 Shot *shot = Shot::shots[i];
8578 if (shot->isActive() && isEntityCollideWithShot(e, shot))
8579 {
8580 Bone *b = collideSkeletalVsCircle(e, shot->position, shot->collideRadius);
8581 if (b)
8582 {
8583 lastCollidePosition = shot->position;
8584 shot->hitEntity(e, b);
8585 }
8586 }
8587 }
8588 }
8589
handleShotCollisionsHair(Entity * e,int num,float perc)8590 void Game::handleShotCollisionsHair(Entity *e, int num, float perc)
8591 {
8592 for (size_t i = 0; i < Shot::shots.size(); ++i)
8593 {
8594 Shot *shot = Shot::shots[i];
8595 if (shot->isActive() && isEntityCollideWithShot(e, shot))
8596 {
8597 bool b = collideHairVsCircle(e, num, shot->position, 8, perc);
8598 if (b)
8599 {
8600 lastCollidePosition = shot->position;
8601 shot->hitEntity(e, 0);
8602 }
8603 }
8604 }
8605 }
8606
8607 #ifdef AQUARIA_BUILD_SCENEEDITOR
toggleSceneEditor()8608 void Game::toggleSceneEditor()
8609 {
8610 if (!core->getAltState())
8611 {
8612 sceneEditor.toggle();
8613 setElementLayerFlags();
8614 }
8615 }
8616 #endif
8617
toggleMiniMapRender()8618 void Game::toggleMiniMapRender()
8619 {
8620 if (miniMapRender)
8621 {
8622 if (miniMapRender->alpha == 0)
8623 miniMapRender->alpha.interpolateTo(1, 0.1f);
8624 else if (!miniMapRender->alpha.isInterpolating())
8625 miniMapRender->alpha.interpolateTo(0, 0.1f);
8626 }
8627 }
8628
8629
toggleMiniMapRender(int v)8630 void Game::toggleMiniMapRender(int v)
8631 {
8632 if (miniMapRender)
8633 {
8634 if (v == 0)
8635 miniMapRender->alpha.interpolateTo(0, 0.1f);
8636 else
8637 miniMapRender->alpha.interpolateTo(1, 0.1f);
8638 }
8639 }
8640
toggleGridRender()8641 void Game::toggleGridRender()
8642 {
8643 float t = 0;
8644 float a = 0;
8645 if (gridRender->alpha == 0)
8646 a = 0.5f;
8647
8648 gridRender->alpha.interpolateTo(a, t);
8649 gridRender2->alpha.interpolateTo(a, t);
8650 gridRender3->alpha.interpolateTo(a, t);
8651 edgeRender->alpha.interpolateTo(a, t);
8652 gridRenderEnt->alpha.interpolateTo(a, t);
8653 gridRenderUser1->alpha.interpolateTo(a, t);
8654 gridRenderUser2->alpha.interpolateTo(a, t);
8655 }
8656
getCameraPositionFor(const Vector & pos)8657 Vector Game::getCameraPositionFor(const Vector &pos)
8658 {
8659 return Vector(pos.x - 400 * core->invGlobalScale, pos.y - 300 * core->invGlobalScale, 0);
8660 }
8661
setParallaxTextureCoordinates(Quad * q,float speed)8662 void Game::setParallaxTextureCoordinates(Quad *q, float speed)
8663 {
8664 //int backgroundImageRepeat = 1.2;
8665 q->followCamera = 1;
8666 q->texture->repeat = true;
8667
8668 float camx = (core->cameraPos.x/800.0f)*speed;
8669 float camy = -(core->cameraPos.y/600.0f)*speed;
8670
8671 float camx1 = camx - float(backgroundImageRepeat)/2.0f;
8672 float camx2 = camx + float(backgroundImageRepeat)/2.0f;
8673 float camy1 = camy - float(backgroundImageRepeat)/2.0f;
8674 float camy2 = camy + float(backgroundImageRepeat)/2.0f;
8675
8676 q->upperLeftTextureCoordinates = Vector(camx1*backgroundImageRepeat, camy1*backgroundImageRepeat);
8677 q->lowerRightTextureCoordinates = Vector(camx2*backgroundImageRepeat, camy2*backgroundImageRepeat);
8678 }
8679
setCameraFollow(Vector * position)8680 void Game::setCameraFollow(Vector *position)
8681 {
8682 cameraFollow = position;
8683 cameraFollowObject = 0;
8684 cameraFollowEntity = 0;
8685 }
8686
setCameraFollow(RenderObject * r)8687 void Game::setCameraFollow(RenderObject *r)
8688 {
8689 cameraFollow = &r->position;
8690 cameraFollowObject = r;
8691 cameraFollowEntity = 0;
8692 }
8693
setCameraFollowEntity(Entity * e)8694 void Game::setCameraFollowEntity(Entity *e)
8695 {
8696 cameraFollow = &e->position;
8697 cameraFollowObject = 0;
8698 cameraFollowEntity = e;
8699 }
8700
updateCurrentVisuals(float dt)8701 void Game::updateCurrentVisuals(float dt)
8702 {
8703 /*
8704 static float delay = 0;
8705 delay += dt;
8706 if (delay > 0.2f)
8707 {
8708 for (Path *p = dsq->game->getFirstPathOfType(PATH_CURRENT); p; p = p->nextOfType)
8709 {
8710 if (p->active)
8711 {
8712 for (int n = 1; n < p->nodes.size(); n++)
8713 {
8714 PathNode *node2 = &p->nodes[n];
8715 PathNode *node1 = &p->nodes[n-1];
8716 Vector dir = node2->position - node1->position;
8717
8718 dir.setLength2D(p->currentMod);
8719 dsq->spawnBubble(node1->position, dir);
8720 }
8721 }
8722
8723 }
8724 delay = 0;
8725 }
8726 */
8727
8728 /*
8729 if (dsq->game->getPath(i)->name == "CURRENT" && dsq->game->getPath(i)->nodes.size() >= 2)
8730 {
8731 Vector dir = dsq->game->getPath(i)->nodes[1].position - dsq->game->getPath(i)->nodes[0].position;
8732 dir.setLength2D(800);
8733 dsq->spawnBubble(dsq->game->getPath(i)->nodes[0].position, dir);
8734 }
8735 */
8736 }
8737
onOptionsMenu()8738 void Game::onOptionsMenu()
8739 {
8740 dsq->screenTransition->capture();
8741 toggleOptionsMenu(true);
8742 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8743 }
8744
onOptionsSave()8745 void Game::onOptionsSave()
8746 {
8747 dsq->user.apply();
8748
8749 if (dsq->user.video.resx != dsq->user_backup.video.resx
8750 || dsq->user.video.resy != dsq->user_backup.video.resy
8751 || dsq->user.video.bits != dsq->user_backup.video.bits
8752 || dsq->user.video.full != dsq->user_backup.video.full
8753 || dsq->user.video.vsync != dsq->user_backup.video.vsync)
8754 {
8755 dsq->resetGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full);
8756 if (dsq->confirm("", "graphics", false, 10)) {
8757 } else {
8758 dsq->user.video.resx = dsq->user_backup.video.resx;
8759 dsq->user.video.resy = dsq->user_backup.video.resy;
8760 dsq->user.video.bits = dsq->user_backup.video.bits;
8761 dsq->user.video.full = dsq->user_backup.video.full;
8762 dsq->user.video.vsync = dsq->user_backup.video.vsync;
8763
8764 dsq->user.apply();
8765
8766 dsq->resetGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full);
8767 }
8768 }
8769
8770 /*
8771 if (dsq->user.video.ripples != dsq->user_backup.video.ripples)
8772 {
8773 if (dsq->user.video.ripples)
8774 {
8775 if (core->frameBuffer.isInited())
8776 {
8777 if (!core->afterEffectManager)
8778 {
8779 core->afterEffectManager = new AfterEffectManager(vars->afterEffectsXDivs, vars->afterEffectsYDivs);
8780 core->afterEffectManager->update(0.0);
8781 core->afterEffectManager->capture();
8782 }
8783
8784 dsq->useFrameBuffer = 1;
8785 }
8786 else
8787 {
8788 dsq->useFrameBuffer = 0;
8789 }
8790 }
8791 else
8792 {
8793 if (core->afterEffectManager)
8794 {
8795 delete core->afterEffectManager;
8796 core->afterEffectManager = 0;
8797 }
8798 }
8799 }
8800 */
8801
8802 if (!keyConfigMenu)
8803 dsq->user.save();
8804
8805 if (keyConfigMenu)
8806 {
8807 AquariaKeyConfig::waitingForInput = 0;
8808 dsq->screenTransition->capture();
8809 toggleKeyConfigMenu(false);
8810 toggleOptionsMenu(true, false, true);
8811 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8812 }
8813 else
8814 {
8815 if (optionsOnly)
8816 {
8817 hideInGameMenu();
8818 }
8819 else
8820 {
8821 dsq->screenTransition->capture();
8822 toggleOptionsMenu(false);
8823 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8824 }
8825 }
8826 }
8827
onOptionsCancel()8828 void Game::onOptionsCancel()
8829 {
8830 if (!keyConfigMenu)
8831 {
8832 dsq->user = dsq->user_backup;
8833 }
8834 else
8835 {
8836 dsq->user.control.actionSet = dsq->user_bcontrol.control.actionSet;
8837 }
8838
8839 dsq->user.apply();
8840
8841 if (keyConfigMenu)
8842 {
8843 AquariaKeyConfig::waitingForInput = 0;
8844 dsq->screenTransition->capture();
8845 toggleKeyConfigMenu(false);
8846 toggleOptionsMenu(true, true, true);
8847 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8848 }
8849 else
8850 {
8851 if (optionsOnly)
8852 {
8853 hideInGameMenu();
8854 }
8855 else
8856 {
8857 dsq->screenTransition->capture();
8858 toggleOptionsMenu(false);
8859 dsq->screenTransition->transition(MENUPAGETRANSTIME);
8860 }
8861 }
8862 }
8863
refreshFoodSlots(bool effects)8864 void Game::refreshFoodSlots(bool effects)
8865 {
8866 for (int i = 0; i < foodSlots.size(); i++)
8867 {
8868 foodSlots[i]->refresh(effects);
8869 }
8870 }
8871
refreshTreasureSlots()8872 void Game::refreshTreasureSlots()
8873 {
8874 for (int i = 0; i < treasureSlots.size(); i++)
8875 {
8876 treasureSlots[i]->refresh();
8877 }
8878 }
8879
togglePetMenu(bool f)8880 void Game::togglePetMenu(bool f)
8881 {
8882 if (optionsMenu)
8883 {
8884 toggleOptionsMenu(false);
8885 }
8886
8887 if (foodMenu)
8888 toggleFoodMenu(false);
8889 if (treasureMenu)
8890 toggleTreasureMenu(false);
8891
8892 if (f && !petMenu)
8893 {
8894 currentMenuPage = MENUPAGE_PETS;
8895
8896 toggleMainMenu(false);
8897
8898 bool hasPet = false;
8899 for (int i = 0; i < petSlots.size(); i++)
8900 {
8901 petSlots[i]->alpha = 1;
8902 bool has = dsq->continuity.getFlag(petSlots[i]->petFlag);
8903 if (has)
8904 {
8905 hasPet = true;
8906 /*
8907 for (int j = 0; j < petSlots.size(); j++)
8908 {
8909 if (j != i)
8910 {
8911 bool has = dsq->continuity.getFlag(petSlots[j]->petFlag);
8912 if (has)
8913 {
8914 if (i == 0 && j == 1)
8915 {
8916
8917 }
8918 }
8919 }
8920 }
8921 */
8922 }
8923 }
8924 // act as if they're all active for now...
8925 if (petSlots.size() == 4)
8926 {
8927 petSlots[0]->setDirMove(DIR_RIGHT, petSlots[1]);
8928 petSlots[0]->setDirMove(DIR_UP, petSlots[2]);
8929 petSlots[0]->setDirMove(DIR_LEFT, petSlots[3]);
8930 petSlots[0]->setDirMove(DIR_DOWN, menu[0]);
8931
8932 menu[0]->setDirMove(DIR_UP, petSlots[0]);
8933
8934 petSlots[1]->setDirMove(DIR_LEFT, petSlots[3]);
8935 petSlots[1]->setDirMove(DIR_UP, petSlots[2]);
8936 petSlots[1]->setDirMove(DIR_DOWN, petSlots[0]);
8937
8938 petSlots[1]->setDirMove(DIR_RIGHT, menu[5]);
8939 menu[5]->setDirMove(DIR_LEFT, petSlots[1]);
8940 menu[5]->setDirMove(DIR_UP, petSlots[1]);
8941
8942 petSlots[2]->setDirMove(DIR_RIGHT, petSlots[1]);
8943 petSlots[2]->setDirMove(DIR_DOWN, petSlots[0]);
8944 petSlots[2]->setDirMove(DIR_LEFT, petSlots[3]);
8945
8946 petSlots[3]->setDirMove(DIR_UP, petSlots[2]);
8947 petSlots[3]->setDirMove(DIR_RIGHT, petSlots[1]);
8948 petSlots[3]->setDirMove(DIR_DOWN, petSlots[0]);
8949 }
8950
8951
8952 for (int i = 0; i < petTips.size(); i++)
8953 {
8954 /*
8955 if (hasPet && i == 0)
8956 {
8957 petTips[i]->alpha = 0;
8958 }
8959 else if (!hasPet && i == 1)
8960 petTips[i]->alpha = 0;
8961 else
8962 petTips[i]->alpha = 1;
8963 */
8964 petTips[i]->alpha = 1;
8965 }
8966
8967 liCrystal->alpha = 1;
8968
8969
8970 menu[7]->setFocus(true);
8971
8972
8973 doMenuSectionHighlight(2);
8974
8975 }
8976 else if (!f && petMenu)
8977 {
8978 for (int i = 0; i < petSlots.size(); i++)
8979 {
8980 petSlots[i]->alpha = 0;
8981 }
8982
8983 for (int i = 0; i < petTips.size(); i++)
8984 {
8985 petTips[i]->alpha = 0;
8986 }
8987
8988 liCrystal->alpha = 0;
8989
8990
8991 menu[5]->setDirMove(DIR_LEFT, 0);
8992 menu[5]->setDirMove(DIR_UP, 0);
8993 menu[0]->setDirMove(DIR_UP, 0);
8994 }
8995
8996 petMenu = f;
8997 }
8998
toggleTreasureMenu(bool f)8999 void Game::toggleTreasureMenu(bool f)
9000 {
9001 //debugLog("toggle treasure menu!");
9002
9003 if (optionsMenu)
9004 toggleOptionsMenu(false);
9005
9006 if (foodMenu)
9007 toggleFoodMenu(false);
9008 if (petMenu)
9009 togglePetMenu(false);
9010
9011 if (f && !treasureMenu)
9012 {
9013 currentMenuPage = MENUPAGE_TREASURES;
9014
9015 treasureMenu = true;
9016 toggleMainMenu(false);
9017
9018 refreshTreasureSlots();
9019
9020 for (int i = 0; i < treasureTips.size(); i++)
9021 treasureTips[i]->alpha = 1;
9022
9023 if (treasureSlots.size() > 8)
9024 {
9025 treasureSlots[0]->setDirMove(DIR_DOWN, menu[0]);
9026 menu[0]->setDirMove(DIR_UP, treasureSlots[0]);
9027
9028 treasureSlots[2]->setDirMove(DIR_RIGHT, menu[5]);
9029 menu[5]->setDirMove(DIR_LEFT, treasureSlots[2]);
9030
9031 treasureSlots[3]->setDirMove(DIR_RIGHT, menu[5]);
9032 }
9033
9034 menu[8]->setFocus(true);
9035
9036 doMenuSectionHighlight(3);
9037
9038 liCrystal->alpha = 1;
9039
9040 circlePageNum->alpha = 1;
9041 }
9042 else if (!f && treasureMenu)
9043 {
9044 treasureMenu = false;
9045
9046 for (int i = 0; i < treasureTips.size(); i++)
9047 treasureTips[i]->alpha = 0;
9048
9049 menu[0]->setDirMove(DIR_UP, 0);
9050 menu[5]->setDirMove(DIR_LEFT, 0);
9051
9052 liCrystal->alpha = 0;
9053
9054 circlePageNum->alpha = 0;
9055 }
9056
9057 for (int i = 0; i < treasureSlots.size(); i++)
9058 {
9059 if (f)
9060 treasureSlots[i]->alpha = 1;
9061 else
9062 treasureSlots[i]->alpha = 0;
9063 }
9064
9065 if (f)
9066 {
9067 nextTreasure->alpha = 1;
9068 prevTreasure->alpha = 1;
9069 use->alpha = 0;
9070
9071 treasureLabel->alpha = 0;
9072 treasureDescription->alpha = 0;
9073 treasureCloseUp->alpha = 0;
9074 }
9075 else
9076 {
9077 nextTreasure->alpha = 0;
9078 prevTreasure->alpha = 0;
9079 use->alpha = 0;
9080
9081 treasureLabel->alpha = 0;
9082 treasureDescription->alpha = 0;
9083 treasureCloseUp->alpha = 0;
9084 }
9085 }
9086
toggleRecipeList(bool on)9087 void Game::toggleRecipeList(bool on)
9088 {
9089 recipeMenu.toggle(on, true);
9090 }
9091
toggleFoodMenu(bool f)9092 void Game::toggleFoodMenu(bool f)
9093 {
9094 if (optionsMenu)
9095 toggleOptionsMenu(false);
9096 if (petMenu)
9097 togglePetMenu(false);
9098 if (treasureMenu)
9099 toggleTreasureMenu(false);
9100
9101
9102 for (int i = 0; i < foodHolders.size(); i++)
9103 {
9104 if (f)
9105 foodHolders[i]->alpha = 1;
9106 else
9107 foodHolders[i]->alpha = 0;
9108 }
9109
9110 if (f)
9111 {
9112 if (dsq->game->avatar)
9113 {
9114 Path *p=0;
9115 if (dsq->continuity.getFlag(FLAG_UPGRADE_WOK) > 0
9116 || ((p=dsq->game->getNearestPath(dsq->game->avatar->position, PATH_COOK))
9117 && p->isCoordinateInside(dsq->game->avatar->position)))
9118 {
9119 //cook->alpha = 1;
9120 foodHolders[0]->alpha = 1;
9121 }
9122 else
9123 {
9124 foodHolders[0]->alpha = 0;
9125 }
9126 }
9127 }
9128
9129 if (f && !foodMenu)
9130 {
9131 currentMenuPage = MENUPAGE_FOOD;
9132
9133 foodMenu = true;
9134
9135 toggleMainMenu(false);
9136
9137 refreshFoodSlots(false);
9138
9139 cook->alpha = 1;
9140 recipes->alpha = 1;
9141
9142 prevFood->alpha = 1;
9143 nextFood->alpha = 1;
9144 foodLabel->alphaMod = 1;
9145 foodDescription->alphaMod = 1;
9146
9147 foodSort->alpha = 1;
9148
9149 for (int i = 0; i < foodTips.size(); i++)
9150 foodTips[i]->alpha = 1;
9151
9152 if (foodSlots.size() >= 16)
9153 {
9154 foodSlots[2]->setDirMove(DIR_RIGHT, menu[5]);
9155 foodSlots[3]->setDirMove(DIR_RIGHT, menu[5]);
9156 menu[5]->setDirMove(DIR_LEFT, foodSlots[2]);
9157
9158 treasureSlots[3]->setDirMove(DIR_RIGHT, menu[5]);
9159
9160 recipes->setDirMove(DIR_UP, foodSlots[15]);
9161 foodSlots[15]->setDirMove(DIR_DOWN, recipes);
9162 foodSlots[14]->setDirMove(DIR_DOWN, recipes);
9163 foodSlots[0]->setDirMove(DIR_DOWN, recipes);
9164
9165 foodSlots[0]->setDirMove(DIR_LEFT, foodSlots[15]);
9166 foodSlots[15]->setDirMove(DIR_RIGHT, foodSlots[0]);
9167
9168 foodSlots[15]->setDirMove(DIR_LEFT, foodSlots[14]);
9169
9170 recipes->setDirMove(DIR_RIGHT, menu[5]);
9171 }
9172
9173 menu[6]->setFocus(true);
9174
9175 doMenuSectionHighlight(1);
9176
9177 liCrystal->alpha = 1;
9178
9179 circlePageNum->alpha = 1;
9180
9181 previewRecipe->alpha = 0;
9182 updatePreviewRecipe();
9183 }
9184 else if (!f && foodMenu)
9185 {
9186 recipeMenu.toggle(false);
9187 foodMenu = false;
9188
9189 cook->alpha = 0;
9190 recipes->alpha = 0;
9191 prevFood->alpha = 0;
9192 nextFood->alpha = 0;
9193 foodLabel->alphaMod = 0;
9194 foodLabel->alpha = 0;
9195 foodDescription->alpha = 0;
9196 foodSort->alpha = 0;
9197 showRecipe->alpha = 0;
9198
9199 liCrystal->alpha = 0;
9200
9201 for (int i = 0; i < foodTips.size(); i++)
9202 foodTips[i]->alpha = 0;
9203
9204 menu[5]->setDirMove(DIR_LEFT, 0);
9205
9206 circlePageNum->alpha = 0;
9207
9208 previewRecipe->alpha = 0;
9209 }
9210
9211 for (int i = 0; i < foodSlots.size(); i++)
9212 {
9213 foodSlots[i]->toggle(f);
9214 }
9215 }
9216
doMenuSectionHighlight(int section)9217 void Game::doMenuSectionHighlight(int section)
9218 {
9219 for (int i = 0; i < 4; i++)
9220 ((AquariaMenuItem*)menu[(5+i)])->quad->alphaMod = 0.8;
9221 //menu[(5+i)]->offset = Vector(0,-2);
9222 ((AquariaMenuItem*)menu[(5+section)])->quad->alphaMod = 1.0;
9223 menuIconGlow->position = menu[5+section]->position;
9224 /*
9225 for (int i = 0; i < 4; i++)
9226 menu[5+i]->color = Vector(0.5, 0.5, 0.5);
9227
9228 menu[5+section]->color = Vector(1,1,1);
9229 */
9230 }
9231
toggleMainMenu(bool f)9232 void Game::toggleMainMenu(bool f)
9233 {
9234 const float t = 0;
9235 if (f)
9236 {
9237 currentMenuPage = MENUPAGE_SONGS;
9238 for (int i = 0; i < songSlots.size(); i++)
9239 {
9240 //songSlots[i]->alpha.interpolateTo(1, t);
9241 songSlots[i]->alphaMod = 1;
9242 }
9243 songBubbles->alpha.interpolateTo(1,t);
9244 energyIdol->alpha.interpolateTo(1,t);
9245 liCrystal->alpha.interpolateTo(1, t);
9246 for (int i = 0; i < songTips.size(); i++)
9247 songTips[i]->alpha = 1;
9248 menuBg2->alpha.interpolateTo(1, t);
9249
9250
9251 int sm=-900;
9252 SongSlot *ss=0;
9253 for (int i = 0; i < songSlots.size(); i++)
9254 {
9255 if (dsq->continuity.hasSong(dsq->continuity.getSongTypeBySlot(i)))
9256 {
9257 //if (songSlots[i]->alpha == 1 && songSlots[i]->renderQuad && songSlots[i]->alphaMod == 1)
9258 {
9259 Vector p = songSlots[i]->getWorldPosition();
9260 if (p.x > sm)
9261 {
9262 sm = p.x;
9263 ss = songSlots[i];
9264 }
9265 }
9266 }
9267 }
9268
9269 if (ss)
9270 {
9271 ss->setDirMove(DIR_RIGHT, (AquariaMenuItem*)menu[5]);
9272 }
9273 ((AquariaMenuItem*)menu[5])->setDirMove(DIR_LEFT, ss);
9274
9275 doMenuSectionHighlight(0);
9276 }
9277 else
9278 {
9279 ((AquariaMenuItem*)menu[5])->setDirMove(DIR_LEFT, 0);
9280
9281 for (int i = 0; i < songSlots.size(); i++)
9282 {
9283 songSlots[i]->alphaMod = 0;
9284 }
9285
9286 for (int i = 0; i < songTips.size(); i++)
9287 songTips[i]->alpha = 0;
9288
9289 songBubbles->alpha.interpolateTo(0, t);
9290 energyIdol->alpha.interpolateTo(0,t);
9291 liCrystal->alpha.interpolateTo(0, t);
9292 }
9293 }
9294
toggleKeyConfigMenu(bool f)9295 void Game::toggleKeyConfigMenu(bool f)
9296 {
9297 const float t = 0;
9298 playingSongInMenu = -1;
9299
9300
9301 if (f && !keyConfigMenu)
9302 {
9303 //dsq->screenTransition->capture();
9304
9305 toggleOptionsMenu(false, false, true);
9306
9307 // Prevent int i from "leaking out" due to Microsoft extension to for-scope
9308 {
9309 for (int i = 0; i <= 1; i++)
9310 menu[i]->alpha.interpolateTo(0, t);
9311 for (int i = 4; i <= 8; i++)
9312 menu[i]->alpha.interpolateTo(0, t);
9313 }
9314
9315 toggleMainMenu(false);
9316
9317 menuBg2->alpha.interpolateTo(0, t);
9318
9319 keyConfigMenu = true;
9320
9321 group_keyConfig->setHidden(false);
9322 group_keyConfig->alpha = 1;
9323
9324 dsq->user_bcontrol = dsq->user;
9325
9326 //group_keyConfig->children[group_keyConfig->children.size()-3]
9327
9328 RenderObject::Children::reverse_iterator i = group_keyConfig->children.rbegin();
9329 AquariaKeyConfig *upright0 = (AquariaKeyConfig*)(*i);
9330 i++;
9331 AquariaKeyConfig *upright = (AquariaKeyConfig*)(*i);
9332 i++; //i++;
9333 AquariaKeyConfig *upleft = (AquariaKeyConfig*)(*i);
9334
9335 opt_cancel->setDirMove(DIR_UP, upright);
9336 upright->setDirMove(DIR_DOWN, opt_cancel);
9337 upright0->setDirMove(DIR_DOWN, opt_cancel);
9338
9339 opt_save->setDirMove(DIR_UP, upleft);
9340 upleft->setDirMove(DIR_DOWN, opt_save);
9341
9342
9343 opt_cancel->alpha = 1;
9344 opt_save->alpha = 1;
9345
9346
9347 opt_save->position = opt_save_original + Vector(0, 120);
9348 opt_cancel->position = opt_cancel_original + Vector(0, 120);
9349
9350 opt_cancel->setFocus(true);
9351
9352 menuIconGlow->alpha = 0;
9353
9354 //dsq->screenTransition->transition(MENUPAGETRANSTIME);
9355 }
9356 else if (!f)
9357 {
9358 keyConfigMenu = false;
9359
9360 group_keyConfig->alpha = 0;
9361 group_keyConfig->setHidden(true);
9362
9363 opt_cancel->alpha = 0;
9364 opt_save->alpha = 0;
9365
9366 opt_save->position = opt_save_original;
9367 opt_cancel->position = opt_cancel_original;
9368
9369 menuIconGlow->alpha = 1;
9370 }
9371 }
9372
toggleOptionsMenu(bool f,bool skipBackup,bool isKeyConfig)9373 void Game::toggleOptionsMenu(bool f, bool skipBackup, bool isKeyConfig)
9374 {
9375 const float t = 0;
9376 playingSongInMenu = -1;
9377
9378 if (f && !optionsMenu)
9379 {
9380 //menuBg->setTexture("gui/options-menu");
9381 //menuBg->setWidthHeight(1024, 1024);
9382
9383 if (!isKeyConfig && !optionsOnly)
9384 {
9385 dsq->continuity.lastOptionsMenuPage = currentMenuPage;
9386 }
9387
9388 toggleFoodMenu(false);
9389 optionsMenu = true;
9390 voxslider->setValue(dsq->user.audio.voxvol);
9391 musslider->setValue(dsq->user.audio.musvol);
9392 sfxslider->setValue(dsq->user.audio.sfxvol);
9393
9394 if (blurEffectsCheck)
9395 blurEffectsCheck->setValue(dsq->user.video.blur);
9396
9397 flipInputButtonsCheck->setValue(dsq->user.control.flipInputButtons);
9398 toolTipsCheck->setValue(dsq->user.control.toolTipsOn);
9399 autoAimCheck->setValue(dsq->user.control.autoAim);
9400 targetingCheck->setValue(dsq->user.control.targeting);
9401
9402 subtitlesCheck->setValue(dsq->user.audio.subtitles);
9403 fullscreenCheck->setValue(dsq->isFullscreen());
9404
9405 if (ripplesCheck)
9406 ripplesCheck->setValue(core->afterEffectManager!=0);
9407
9408 if (micInputCheck)
9409 micInputCheck->setValue(dsq->user.audio.micOn);
9410
9411 if (resBox)
9412 {
9413 std::ostringstream os;
9414 os << core->width << "x" << core->height;
9415 if (!resBox->setSelectedItem(os.str()))
9416 {
9417 resBox->addItem(os.str());
9418 resBox->setSelectedItem(os.str());
9419 }
9420 }
9421
9422 opt_cancel->setDirMove(DIR_UP, targetingCheck);
9423 targetingCheck->setDirMove(DIR_DOWN, opt_cancel);
9424
9425
9426 opt_save->setDirMove(DIR_UP, voxslider);
9427 voxslider->setDirMove(DIR_DOWN, opt_save);
9428
9429 keyConfigButton->setDirMove(DIR_UP, targetingCheck);
9430
9431 if (!skipBackup)
9432 dsq->user_backup = dsq->user;
9433
9434
9435 options->alpha.interpolateTo(1, t);
9436
9437 for (int i = 0; i <= 1; i++)
9438 menu[i]->alpha.interpolateTo(0, t);
9439 for (int i = 4; i <= 9; i++)
9440 menu[i]->alpha.interpolateTo(0, t);
9441
9442 toggleMainMenu(false);
9443
9444 keyConfigButton->alpha = 1;
9445
9446 menuBg2->alpha.interpolateTo(0, t);
9447
9448 opt_cancel->alpha = 1;
9449 opt_save->alpha = 1;
9450 opt_cancel->setFocus(true);
9451
9452 lips->alpha = 0;
9453
9454 liCrystal->alpha = 1;
9455
9456 optionsMenu = true;
9457
9458 menuIconGlow->alpha = 0;
9459
9460 /*
9461 for (int i = 0; i < menu.size(); i++)
9462 menu[i]->alpha.interpolateTo(0, 0.2);
9463 */
9464 }
9465 else if (!f && optionsMenu)
9466 {
9467 lips->alpha = 0;
9468
9469 keyConfigButton->alpha = 0;
9470
9471 options->alpha.interpolateTo(0, t);
9472
9473 opt_cancel->alpha = 0;
9474 opt_save->alpha = 0;
9475
9476 liCrystal->alpha = 0;
9477
9478 /*
9479 // what does this do?
9480 if (optionsMenu)
9481 ((AquariaMenuItem*)menu[4])->setFocus(true);
9482 */
9483 //((AquariaMenuItem*)menu[5])->setFocus(true);
9484
9485 optionsMenu = false;
9486
9487
9488
9489 if (!optionsOnly)
9490 {
9491 for (int i = 0; i <= 1; i++)
9492 menu[i]->alpha.interpolateTo(1, t);
9493 for (int i = 4; i <= 9; i++)
9494 {
9495 menu[i]->alpha.interpolateTo(1, t);
9496 }
9497
9498 //menu[9]->alpha = 1;
9499
9500 if (!isKeyConfig)
9501 {
9502 switch(dsq->continuity.lastOptionsMenuPage)
9503 {
9504 case MENUPAGE_FOOD:
9505 toggleFoodMenu(true);
9506 ((AquariaMenuItem*)menu[6])->setFocus(true);
9507 break;
9508 case MENUPAGE_TREASURES:
9509 toggleTreasureMenu(true);
9510 ((AquariaMenuItem*)menu[8])->setFocus(true);
9511 break;
9512 case MENUPAGE_PETS:
9513 togglePetMenu(true);
9514 ((AquariaMenuItem*)menu[7])->setFocus(true);
9515 break;
9516 case MENUPAGE_SONGS:
9517 default:
9518 toggleMainMenu(true);
9519 ((AquariaMenuItem*)menu[5])->setFocus(true);
9520 break;
9521 }
9522 }
9523
9524 //((AquariaMenuItem*)menu[4])->setFocus(true);
9525
9526
9527 menuBg2->alpha.interpolateTo(1, t);
9528 }
9529
9530 menuIconGlow->alpha = 1;
9531
9532 }
9533 }
9534
9535 float optsfxdly = 0;
updateOptionsMenu(float dt)9536 void Game::updateOptionsMenu(float dt)
9537 {
9538 if (optionsMenu)
9539 {
9540 dsq->user.audio.voxvol = voxslider->getValue();
9541 dsq->user.audio.sfxvol = sfxslider->getValue();
9542 dsq->user.audio.musvol = musslider->getValue();
9543
9544 if (micInputCheck)
9545 dsq->user.audio.micOn = micInputCheck->getValue();
9546
9547 dsq->user.control.flipInputButtons = flipInputButtonsCheck->getValue();
9548 dsq->user.control.toolTipsOn = toolTipsCheck->getValue();
9549 dsq->user.control.autoAim = autoAimCheck->getValue();
9550 dsq->user.control.targeting = targetingCheck->getValue();
9551
9552 dsq->user.audio.subtitles = subtitlesCheck->getValue();
9553 dsq->user.video.full = fullscreenCheck->getValue();
9554
9555 if (ripplesCheck)
9556 dsq->user.video.fbuffer = ripplesCheck->getValue();
9557
9558 if (blurEffectsCheck)
9559 dsq->user.video.blur = blurEffectsCheck->getValue();
9560
9561 if (resBox)
9562 {
9563 std::string s = resBox->getSelectedItemString();
9564 if (!s.empty())
9565 {
9566 int pos = s.find('x');
9567 std::istringstream is1(s.substr(0, pos));
9568 is1 >> dsq->user.video.resx;
9569 std::istringstream is2(s.substr(pos+1, s.size()-(pos+1)));
9570 is2 >> dsq->user.video.resy;
9571 }
9572
9573 }
9574
9575 /*
9576 dsq->user.audio.sfxvol = sfxslider->getValue();
9577 dsq->user.audio.musvol = musslider->getValue();
9578 */
9579
9580 optsfxdly += dt;
9581 if (sfxslider->hadInput())
9582 {
9583 dsq->sound->playSfx("denied");
9584 }
9585 else if (voxslider->hadInput())
9586 {
9587 if (!dsq->sound->isPlayingVoice())
9588 dsq->voice("naija_somethingfamiliar");
9589 }
9590 else if (optsfxdly > 0.6f)
9591 {
9592 optsfxdly = 0;
9593 if (sfxslider->isGrabbed())
9594 {
9595 dsq->sound->playSfx("denied");
9596 dsq->loops.updateVolume();
9597 if (dsq->game->avatar)
9598 dsq->game->avatar->updateHeartbeatSfx();
9599 }
9600 if (voxslider->isGrabbed())
9601 {
9602 if (!dsq->sound->isPlayingVoice())
9603 {
9604 dsq->voice("naija_somethingfamiliar");
9605 }
9606 }
9607 }
9608
9609 /*
9610 std::ostringstream os;
9611 os << "musvol: " << dsq->user.audio.musvol;
9612 debugLog(os.str());
9613 */
9614
9615 dsq->user.apply();
9616 }
9617 }
9618
updateInGameMenu(float dt)9619 void Game::updateInGameMenu(float dt)
9620 {
9621 if (isInGameMenu())
9622 {
9623 menuOpenTimer += dt;
9624 if (dt > 10)
9625 dt = 10;
9626
9627 if (foodMenu)
9628 {
9629 if (dsq->inputMode == INPUT_JOYSTICK)
9630 {
9631 //debugLog("food menu, joystick");
9632
9633
9634 /*
9635 */
9636 }
9637
9638 if (dsq->continuity.hasIngredients())
9639 {
9640 int pageNum = (currentFoodPage+1);
9641 int numPages = ((dsq->continuity.ingredientCount()-1)/foodPageSize)+1;
9642
9643 std::ostringstream os;
9644 os << pageNum << "/" << numPages;
9645 circlePageNum->setText(os.str());
9646
9647 if (pageNum > numPages && pageNum > 1)
9648 {
9649 onPrevFoodPage();
9650 }
9651 }
9652 else
9653 {
9654 circlePageNum->setText("1/1");
9655 }
9656 }
9657 if (treasureMenu)
9658 {
9659 std::ostringstream os;
9660 os << (currentTreasurePage+1) << "/" << (numTreasures/treasurePageSize);
9661 circlePageNum->setText(os.str());
9662 }
9663 // HACK: move this later
9664 updateOptionsMenu(dt);
9665 if (playingSongInMenu != -1)
9666 {
9667 songMenuPlayDelay += dt;
9668
9669 Song s = dsq->continuity.songBank[playingSongInMenu];
9670
9671 if (currentSongMenuNote < s.notes.size())
9672 {
9673 if (songMenuPlayDelay >= 0.5f)
9674 {
9675 songMenuPlayDelay = 0;
9676
9677
9678 if (currentSongMenuNote >= 0 && currentSongMenuNote < s.notes.size())
9679 {
9680 /*
9681 std::ostringstream os;
9682 os << "MenuNote" << s[currentSongMenuNote];
9683 */
9684 sound->playSfx(dsq->game->getNoteName(s.notes[currentSongMenuNote], "Menu"));
9685
9686 float a = (s.notes[currentSongMenuNote]*2*PI)/8.0f;
9687 int sz = 110*menuBg->scale.x;
9688 Vector notePos(sinf(a)*sz,cosf(a)*sz);
9689
9690 float t = 0.5;
9691 Quad *q = new Quad("particles/glow", Vector(400+237*menuBg->scale.x,300-52*menuBg->scale.x)+notePos);
9692 q->setBlendType(RenderObject::BLEND_ADD);
9693 q->scale = Vector(5,5);
9694 q->alpha.ensureData();
9695 q->alpha.data->path.addPathNode(0, 0);
9696 q->alpha.data->path.addPathNode(0.75, 0.5);
9697 q->alpha.data->path.addPathNode(0.75, 0.5);
9698 q->alpha.data->path.addPathNode(0, 1);
9699 q->alpha.startPath(t);
9700 q->followCamera = 1;
9701 q->setLife(t);
9702 q->setDecayRate(1);
9703
9704 game->addRenderObject(q, LR_HUD);
9705
9706 currentSongMenuNote++;
9707 }
9708 else
9709 {
9710
9711 /*
9712 if (playedDudNote)
9713 playingSongInMenu = -1;
9714 else
9715 playedDudNote = true;
9716 */
9717 }
9718 }
9719 }
9720 else
9721 {
9722 if (songMenuPlayDelay >= 1.0f)
9723 {
9724 playingSongInMenu = -1;
9725 }
9726 }
9727 }
9728 }
9729 }
9730
9731
updateCursor(float dt)9732 void Game::updateCursor(float dt)
9733 {
9734 bool rotate = false;
9735
9736 if (dsq->inputMode == INPUT_MOUSE)
9737 {
9738 dsq->cursor->offset.stop();
9739 dsq->cursor->offset = Vector(0,0);
9740 //debugLog("offset lerp stop in mouse!");
9741 }
9742 else if (dsq->inputMode == INPUT_JOYSTICK)
9743 {
9744 if (!dsq->game->isPaused() || dsq->game->isInGameMenu() || !dsq->game->avatar->isInputEnabled())
9745 {
9746 int offy = -60;
9747 if (dsq->game->isInGameMenu() || !dsq->game->avatar->isInputEnabled())
9748 {
9749 //cursor->setTexture("");
9750 offy = 0;
9751 }
9752 if (!dsq->cursor->offset.isInterpolating())
9753 {
9754 //debugLog("offset lerp!");
9755 dsq->cursor->offset = Vector(0, offy);
9756 dsq->cursor->offset.interpolateTo(Vector(0, offy-20), 0.4, -1, 1, 1);
9757 }
9758 }
9759 else
9760 {
9761 //debugLog("offset lerp stop in joystick!");
9762 dsq->cursor->offset.stop();
9763 dsq->cursor->offset = Vector(0,0);
9764 }
9765 }
9766
9767 if (isSceneEditorActive() || dsq->game->isPaused() || (!avatar || !avatar->isInputEnabled()) ||
9768 (dsq->game->miniMapRender && dsq->game->miniMapRender->isCursorIn())
9769 )
9770 {
9771 dsq->setCursor(CURSOR_NORMAL);
9772 // Don't show the cursor in keyboard/joystick mode if it's not
9773 // already visible (this keeps the cursor from appearing for an
9774 // instant during map fadeout).
9775 if (dsq->inputMode == INPUT_MOUSE || isSceneEditorActive() || dsq->game->isPaused())
9776 dsq->cursor->alphaMod = 0.5;
9777
9778 /*
9779 dsq->cursor->offset.stop();
9780 dsq->cursor->offset = Vector(0,0);
9781 */
9782 }
9783 else if (avatar)
9784 {
9785 //Vector v = avatar->getVectorToCursorFromScreenCentre();
9786 if (dsq->inputMode == INPUT_JOYSTICK)// && !avatar->isSinging() && !dsq->game->isInGameMenu() && !dsq->game->isPaused())
9787 {
9788 dsq->cursor->alphaMod = 0;
9789 if (!avatar->isSinging())
9790 core->setMousePosition(core->center);
9791 if (!dsq->game->isPaused())
9792 {
9793 /*
9794
9795 */
9796 }
9797
9798 }
9799 else
9800 {
9801 dsq->cursor->offset.stop();
9802 dsq->cursor->offset = Vector(0,0);
9803
9804 dsq->cursor->alphaMod = 0.5;
9805 }
9806 Vector v = avatar->getVectorToCursor();
9807 if (avatar->looking)
9808 {
9809 dsq->setCursor(CURSOR_LOOK);
9810 }
9811 else if (avatar->isSinging())
9812 {
9813 dsq->setCursor(CURSOR_SING);
9814 }
9815 else if (dsq->game->isInGameMenu() || v.isLength2DIn(avatar->getStopDistance()) || (avatar->entityToActivate || avatar->pathToActivate))
9816 {
9817 dsq->setCursor(CURSOR_NORMAL);
9818 }
9819 else if (!v.isLength2DIn(avatar->getBurstDistance()) /*|| avatar->state.lockedToWall*/ /*|| avatar->bursting*/)
9820 {
9821 dsq->setCursor(CURSOR_BURST);
9822 rotate = true;
9823 }
9824 else
9825 {
9826 dsq->setCursor(CURSOR_SWIM);
9827 rotate = true;
9828 }
9829 }
9830 if (rotate)
9831 {
9832 if (avatar)
9833 {
9834 Vector vec = dsq->getGameCursorPosition() - avatar->position;
9835 float angle=0;
9836 MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), vec, angle);
9837 angle = 180-(360-angle);
9838 angle += 90;
9839 dsq->cursor->rotation.z = angle;
9840 }
9841 }
9842 else
9843 {
9844 dsq->cursor->rotation.z = 0;
9845 }
9846 }
9847
constrainCamera()9848 void Game::constrainCamera()
9849 {
9850 cameraOffBounds = 0;
9851 if (cameraConstrained)
9852 {
9853 float vw2 = core->getVirtualOffX()*core->invGlobalScale;
9854 float vh2 = core->getVirtualOffY()*core->invGlobalScale;
9855
9856 if (dsq->cameraPos.x - vw2 < (cameraMin.x+1))
9857 {
9858 dsq->cameraPos.x = (cameraMin.x+1) + vw2;
9859 cameraOffBounds = 1;
9860 }
9861
9862 if (dsq->cameraPos.y <= (cameraMin.y+1))
9863 {
9864 dsq->cameraPos.y = (cameraMin.y+1) + vh2;
9865 cameraOffBounds = 1;
9866 }
9867
9868 // The camera is positioned at (0, 0) screen coordinates, which, on widescreen resolutions,
9869 // is *not* the upper left corner. Subtract the offset to get the real position.
9870 // HACK: One column shows through after blackness ends, adding TILE_SIZE fixes this. -- fg
9871 float scrw = (core->getVirtualWidth()-core->getVirtualOffX()+TILE_SIZE)*core->invGlobalScale;
9872 float scrh = 600*core->invGlobalScale;
9873
9874 if (cameraMax.x != -1 && dsq->cameraPos.x + scrw >= cameraMax.x)
9875 {
9876 dsq->cameraPos.x = cameraMax.x - scrw;
9877 cameraOffBounds = 1;
9878 }
9879
9880 if (cameraMax.y != -1 && dsq->cameraPos.y + scrh >= cameraMax.y)
9881 {
9882 dsq->cameraPos.y = cameraMax.y - scrh;
9883 cameraOffBounds = 1;
9884 }
9885 }
9886 }
9887
areEntitiesUnique()9888 bool areEntitiesUnique()
9889 {
9890 bool unique = true;
9891 int c = 0;
9892
9893 FOR_ENTITIES(i)
9894 {
9895 Entity *e = *i;
9896 FOR_ENTITIES(j)
9897 {
9898 Entity *e2 = *j;
9899 if (e != e2)
9900 {
9901 if (e->getID() == e2->getID())
9902 {
9903 std::ostringstream os;
9904 os << "found non-unique entity: " << e->getID() << " names, " << e->name << " and " << e2->name;
9905 debugLog(os.str());
9906 unique = false;
9907 c++;
9908 }
9909 }
9910 }
9911 }
9912 if (unique)
9913 {
9914 debugLog("Entity IDs are unique");
9915 }
9916 else
9917 {
9918 std::ostringstream os;
9919 os << c << " Entity IDs are NOT unique";
9920 debugLog(os.str());
9921 }
9922 return unique;
9923 }
9924
isControlHint()9925 bool Game::isControlHint()
9926 {
9927 return controlHint_bg->alpha.x != 0;
9928 }
9929
trace(Vector start,Vector target)9930 bool Game::trace(Vector start, Vector target)
9931 {
9932 /*
9933 TileVector tstart(start);
9934 TileVector ttarget(target);
9935 */
9936 int i = 0;
9937 Vector mov(target-start);
9938 Vector pos = start;
9939 //mov.normalize2D();
9940 //mov |= g;
9941 //mov |= 0.5;
9942 mov.setLength2D(TILE_SIZE*1);
9943 int c = 0;
9944 // 1024
9945 while (c < 2048*10)
9946 {
9947 pos += mov;
9948
9949
9950 if (dsq->game->isObstructed(TileVector(pos)))
9951 return false;
9952
9953
9954 //Vector diff(tstart.x - ttarget.x, tstart.y - ttarget.y);
9955 Vector diff = target - pos;
9956 if (diff.getSquaredLength2D() <= sqr(TILE_SIZE*2))
9957 //close enough!
9958 return true;
9959
9960 Vector pl = mov.getPerpendicularLeft();
9961 Vector pr = mov.getPerpendicularRight();
9962 i = 1;
9963 for (i = 1; i <= 6; i++)
9964 {
9965 TileVector tl(pos + pl*i);//(start.x + pl.x*i, start.y + pl.y*i);
9966 TileVector tr(pos + pr*i);//(start.x + pr.x*i, start.y + pr.y*i);
9967 if (dsq->game->isObstructed(tl) || dsq->game->isObstructed(tr))
9968 return false;
9969 }
9970
9971 c++;
9972 }
9973 return false;
9974 }
9975
9976 const float bgLoopFadeTime = 1;
updateBgSfxLoop()9977 void Game::updateBgSfxLoop()
9978 {
9979 if (!avatar) return;
9980
9981 Path *p = getNearestPath(dsq->game->avatar->position, PATH_BGSFXLOOP);
9982 if (p && p->isCoordinateInside(dsq->game->avatar->position) && !p->content.empty())
9983 {
9984 if (bgSfxLoopPlaying2 != p->content)
9985 {
9986 if (dsq->loops.bg2 != BBGE_AUDIO_NOCHANNEL)
9987 {
9988 core->sound->fadeSfx(dsq->loops.bg2, SFT_OUT, bgLoopFadeTime);
9989 dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL;
9990 bgSfxLoopPlaying2 = "";
9991 }
9992 PlaySfx play;
9993 play.name = p->content;
9994 play.time = bgLoopFadeTime;
9995 play.fade = SFT_IN;
9996 play.vol = 1;
9997 play.loops = -1;
9998 play.priority = 0.7;
9999 dsq->loops.bg2 = core->sound->playSfx(play);
10000 bgSfxLoopPlaying2 = p->content;
10001 }
10002 }
10003 else
10004 {
10005 if (dsq->loops.bg2 != BBGE_AUDIO_NOCHANNEL)
10006 {
10007 core->sound->fadeSfx(dsq->loops.bg2, SFT_OUT, bgLoopFadeTime);
10008 dsq->loops.bg2 = BBGE_AUDIO_NOCHANNEL;
10009 bgSfxLoopPlaying2 = "";
10010 }
10011 }
10012
10013 if (avatar->isUnderWater(avatar->getHeadPosition()))
10014 {
10015 dsq->game->switchBgLoop(0);
10016 }
10017 else
10018 dsq->game->switchBgLoop(1);
10019 }
10020
10021 const float helpTextScrollSpeed = 800.0f;
10022 const float helpTextScrollClickAmount = 340.0f;
10023 const float helpTextScrollClickTime = -helpTextScrollSpeed;
onHelpDown()10024 void Game::onHelpDown()
10025 {
10026 float to = helpText->offset.y - helpTextScrollClickAmount;
10027 if (to < -helpText->getHeight() + core->getVirtualHeight())
10028 {
10029 to = -helpText->getHeight() + core->getVirtualHeight();
10030 }
10031 helpText->offset.interpolateTo(Vector(0, to), helpTextScrollClickTime);
10032 }
10033
onHelpUp()10034 void Game::onHelpUp()
10035 {
10036 float to = helpText->offset.y + helpTextScrollClickAmount;
10037 if (to > 0)
10038 {
10039 to = 0;
10040 }
10041 helpText->offset.interpolateTo(Vector(0, to), helpTextScrollClickTime);
10042 }
10043
update(float dt)10044 void Game::update(float dt)
10045 {
10046 particleManager->clearInfluences();
10047
10048 if (inHelpScreen)
10049 {
10050 const float helpTextScrollSpeed = 400.0f;
10051 if (isActing(ACTION_SWIMDOWN))
10052 {
10053 helpText->offset.stop();
10054 helpText->offset.y -= helpTextScrollSpeed * dt;
10055 if (helpText->offset.y < -helpText->getHeight() + core->getVirtualHeight())
10056 {
10057 helpText->offset.y = -helpText->getHeight() + core->getVirtualHeight();
10058 }
10059 }
10060 if (isActing(ACTION_SWIMUP))
10061 {
10062 helpText->offset.stop();
10063 helpText->offset.y += helpTextScrollSpeed * dt;
10064 if (helpText->offset.y > 0)
10065 {
10066 helpText->offset.y = 0;
10067 }
10068 }
10069 }
10070 if (enqueuedPreviewRecipe)
10071 {
10072 updatePreviewRecipe();
10073 enqueuedPreviewRecipe = 0;
10074 }
10075
10076 if (moveFoodSlotToFront)
10077 {
10078 moveFoodSlotToFront->moveToFront();
10079 moveFoodSlotToFront = 0;
10080 }
10081
10082 if (ingOffYTimer > 0)
10083 {
10084 ingOffYTimer -= dt;
10085 if (ingOffYTimer < 0)
10086 {
10087 ingOffYTimer = 0;
10088 ingOffY = 0;
10089 }
10090 }
10091
10092 if (cookDelay > 0)
10093 {
10094 cookDelay -= dt;
10095 if (cookDelay < 0)
10096 cookDelay = 0;
10097 }
10098
10099 if (avatar)
10100 {
10101 /*tintColor.update(dt);
10102 if (core->afterEffectManager)
10103 {
10104 if (tintColor.isInterpolating())
10105 core->afterEffectManager->setActiveShader(AS_GLOW);
10106 else
10107 core->afterEffectManager->setActiveShader(AS_NONE);
10108
10109 core->afterEffectManager->glowShader.setValue(tintColor.x, tintColor.y, tintColor.z, 1);
10110 }*/
10111
10112 if (avatar->isRolling())
10113 particleManager->addInfluence(ParticleInfluence(avatar->position, 300, 800, true));
10114 else if (avatar->isCharging())
10115 particleManager->addInfluence(ParticleInfluence(avatar->position, 100, 600, true));
10116 else if (avatar->bursting)
10117 particleManager->addInfluence(ParticleInfluence(avatar->position, 400, 200, true));
10118 else
10119 particleManager->addInfluence(ParticleInfluence(avatar->position, avatar->vel.getLength2D(), 24, false));
10120
10121
10122 particleManager->setSuckPosition(0, avatar->position);
10123 particleManager->setSuckPosition(1, avatar->position + avatar->vel + avatar->vel2);
10124
10125 //avatar->vel.getLength2D()
10126 /*
10127 for (Shot::Shots::iterator i = Shot::shots.begin(); i != Shot::shots.end(); i++)
10128 {
10129 Emitter::addInfluence(ParticleInfluence((*i)->position, 400, 128, true));
10130 }
10131 */
10132 /*
10133 FOR_ENTITIES (i)
10134 {
10135 Entity *e = *i;
10136 if (e->getEntityType() != ET_AVATAR && e->collideRadius > 0)
10137 {
10138 Emitter::addInfluence(ParticleInfluence(e->position, 200, e->collideRadius, false));
10139 }
10140 }
10141 */
10142 }
10143 updateParticlePause();
10144 //areEntitiesUnique();
10145 if (controlHintTimer > 0)
10146 {
10147 controlHintTimer -= dt;
10148 if (controlHintTimer < 0)
10149 {
10150 controlHint_ignoreClear = false;
10151 clearControlHint();
10152 }
10153 }
10154 dsq->continuity.update(dt);
10155
10156 StateObject::update(dt);
10157
10158
10159 for (ElementUpdateList::iterator e = elementUpdateList.begin(); e != elementUpdateList.end(); e++)
10160 {
10161 (*e)->update(dt);
10162 }
10163
10164
10165 int i = 0;
10166 for (i = 0; i < dsq->game->getNumPaths(); i++)
10167 {
10168 dsq->game->getPath(i)->update(dt);
10169 }
10170
10171 FOR_ENTITIES(j)
10172 {
10173 (*j)->postUpdate(dt);
10174 }
10175
10176 FlockEntity::updateFlockData();
10177
10178 updateCurrentVisuals(dt);
10179 updateCursor(dt);
10180
10181 updateBgSfxLoop();
10182 /*
10183 for (int i = 0; i < 2; i++)
10184 dsq->spawnBubble(Vector(rand()%800 + core->cameraPos.x, rand()%600 + core->cameraPos.y, -0.05f), Vector(0, 0,0));
10185 */
10186
10187 // spawn bubbles
10188 /*
10189 const float spawnTime = 0.008;
10190 static float bubbleTimer = 0;
10191 bubbleTimer += dt;
10192 int sx1, sx2, sy1, sy2;
10193 int extra = 300;
10194 sx1 = core->screenCullX1 - extra;
10195 sx2 = core->screenCullX2 + extra;
10196 sy1 = core->screenCullY1 - extra;
10197 sy2 = core->screenCullY2 + extra;
10198
10199 while (bubbleTimer >= spawnTime)
10200 {
10201 Vector p(sx1 + rand()%(sx2-sx1),sy1 + rand()%(sy2-sy1));
10202 Quad *q = new Quad;
10203 q->scale = Vector(0.25,0.25);
10204 q->position = p;
10205 q->setTexture("bubble");
10206 q->setLife(2);
10207 q->setDecayRate(1);
10208 q->alpha = 0;
10209 q->alpha.interpolateTo(0.4, 1, 1, 1, 1);
10210 addRenderObject(q, LR_ELEMENTS3);
10211 q->velocity = Vector(((rand()%200)-100)/100.0f, ((rand()%200)-100)/100.0f);
10212 q->velocity *= 32;
10213 bubbleTimer -= spawnTime;
10214 }
10215 */
10216
10217 sceneColor.update(dt);
10218 sceneColor2.update(dt);
10219 sceneColor3.update(dt);
10220 dsq->sceneColorOverlay->color = sceneColor * sceneColor2 * sceneColor3;
10221 if (bg)
10222 {
10223 setParallaxTextureCoordinates(bg, 0.3);
10224 }
10225 if (bg2)
10226 {
10227 setParallaxTextureCoordinates(bg2, 0.1);
10228 }
10229 updateInGameMenu(dt);
10230 if (avatar && grad && bg && bg2)
10231 {
10232 //float d = avatar->position.y / float(40000.0);
10233
10234 /*
10235 Vector top1(0.6, 0.8, 0.65);
10236 Vector top2(0.1, 0.2, 0.4);
10237 Vector btm1(0.1, 0.2, 0.4);
10238 Vector btm2(0, 0, 0.1);
10239 */
10240 /*
10241 Vector top1(0.5, 0.65, 7);
10242 Vector top2(0.2, 0.25, 0.3);
10243 Vector btm1(0.2, 0.25, 0.3);
10244 Vector btm2(0, 0, 0.1);
10245 */
10246
10247 /*
10248 // dynamic gradient
10249 Vector top1(99/256.0f, 166/256.0f, 170/256.0f);
10250 Vector top2(86/256.0f, 150/256.0f, 154/256.0f);
10251 Vector btm1(86/256.0f, 150/256.0f, 154/256.0f);
10252 Vector btm2(66/256.0f, 109/256.0f, 122/256.0f);
10253 btm2 *= 0.75;
10254
10255
10256 Vector newtop1(105/256.0f, 190/256.0f, 200/256.0f);
10257
10258 grad->makeVertical(newtop1, btm2);
10259 */
10260
10261
10262
10263 //grad->makeVertical(top1*(1.0-d) + top2*(d), btm1*(1.0-d) + btm2*(d));
10264 /*
10265 float range = 0.5f;
10266 float left = 1.0f - range;
10267 float v = ((range-(d*range)) + left);
10268 bg->color = Vector(v,v,v);
10269 bg2->color = Vector(v,v,v);
10270 */
10271
10272 }
10273
10274 #ifdef AQUARIA_BUILD_SCENEEDITOR
10275 {
10276 sceneEditor.update(dt);
10277 }
10278 #endif
10279
10280 dsq->emote.update(dt);
10281
10282 if (!isPaused())
10283 {
10284 timer += dt;
10285 while (timer > 1.0f)
10286 timer -= 1.0f;
10287
10288 halfTimer += dt*0.5f;
10289 while (halfTimer > 1.0f)
10290 halfTimer -= 1.0f;
10291 }
10292
10293
10294 if (avatar && (avatar->isEntityDead() || avatar->health <= 0) && core->getNestedMains()==1 && !isPaused())
10295 {
10296 dsq->stopVoice();
10297 /*
10298 if (runGameOverScript && dsq->runScript("scripts/maps/" + sceneName + ".lua", "gameOver"))
10299 {
10300 // no game over for you!
10301 }
10302 else
10303 */
10304 if (deathTimer > 0)
10305 {
10306 deathTimer -= dt;
10307 if (deathTimer <= 0)
10308 {
10309 // run game over script
10310
10311 //errorLog("here");
10312 core->enqueueJumpState("GameOver");
10313 }
10314 }
10315 }
10316 if (avatar && avatar->isSinging() && avatar->songInterfaceTimer > 0.5f)
10317 {
10318 avatar->entityToActivate = 0;
10319 avatar->pathToActivate = 0;
10320 }
10321
10322 if (avatar && core->getNestedMains() == 1 && !isPaused() && !avatar->isSinging() && activation)
10323 // && dsq->continuity.form == FORM_NORMAL
10324 {
10325 dsq->continuity.refreshAvatarData(avatar);
10326
10327 Vector bigGlow(3,3);
10328 float bigGlowTime = 0.4;
10329 bool hadThingToActivate = (avatar->entityToActivate!=0 || avatar->pathToActivate!=0);
10330 avatar->entityToActivate = 0;
10331
10332 if (avatar->canActivateStuff())
10333 {
10334 FOR_ENTITIES(i)
10335 {
10336 Entity *e = *i;
10337 float sqrLen = (dsq->getGameCursorPosition() - e->position).getSquaredLength2D();
10338 if (sqrLen < sqr(e->activationRadius)
10339 && (avatar->position-e->position).getSquaredLength2D() < sqr(e->activationRange)
10340 && e->activationType == Entity::ACT_CLICK
10341 && !e->position.isInterpolating()
10342 )
10343 {
10344 //if (trace(avatar->position, e->position))
10345 {
10346 avatar->entityToActivate = e;
10347 dsq->cursorGlow->alpha.interpolateTo(1, 0.2);
10348 dsq->cursorBlinker->alpha.interpolateTo(1.0,0.1);
10349 if (!hadThingToActivate)
10350 {
10351 dsq->cursorGlow->scale = Vector(1,1);
10352 dsq->cursorGlow->scale.interpolateTo(bigGlow,bigGlowTime,1, -1, 1);
10353 }
10354 }
10355 break;
10356 }
10357 }
10358 }
10359
10360 avatar->pathToActivate = 0;
10361 //if (!avatar->entityToActivate && !avatar->state.lockedToWall)
10362
10363
10364 // make sure you also disable entityToActivate
10365 if (dsq->game && dsq->game->avatar->canActivateStuff())
10366 {
10367 Path* p = dsq->game->getScriptedPathAtCursor(true);
10368 if (p && p->cursorActivation)
10369 {
10370 Vector diff = p->nodes[0].position - dsq->game->avatar->position;
10371
10372 if (p->isCoordinateInside(dsq->game->avatar->position) || diff.getSquaredLength2D() < sqr(p->activationRange))
10373 {
10374 //if (trace(avatar->position, p->nodes[0].position))
10375 {
10376 avatar->pathToActivate = p;
10377 dsq->cursorGlow->alpha.interpolateTo(1,0.2);
10378 dsq->cursorBlinker->alpha.interpolateTo(1,0.2);
10379 if (!hadThingToActivate)
10380 {
10381 dsq->cursorGlow->scale = Vector(1,1);
10382 dsq->cursorGlow->scale.interpolateTo(bigGlow,bigGlowTime,1, -1, 1);
10383 }
10384 }
10385 }
10386 }
10387 }
10388
10389 /*
10390 if (!hadThingToActivate && (avatar->entityToActivate || avatar->pathToActivate))
10391 {
10392 debugLog("Spawning cursor particles");
10393 dsq->spawnParticleEffect("CursorBurst", dsq->getGameCursorPosition());
10394 }
10395 */
10396 }
10397
10398 if (!activation)
10399 {
10400 avatar->entityToActivate = 0;
10401 avatar->pathToActivate = 0;
10402 }
10403
10404 if (!avatar->entityToActivate && !avatar->pathToActivate)
10405 {
10406 dsq->cursorGlow->alpha.interpolateTo(0, 0.2);
10407 dsq->cursorBlinker->alpha.interpolateTo(0, 0.1);
10408 }
10409
10410 if (!isSceneEditorActive())
10411 {
10412 if (!isPaused())
10413 waterLevel.update(dt);
10414
10415 if (cameraFollow)
10416 {
10417 Vector dest = *cameraFollow;
10418
10419 if (avatar)
10420 {
10421 if (avatar->looking && !dsq->game->isPaused()) {
10422 Vector diff = avatar->getAim();//dsq->getGameCursorPosition() - avatar->position;
10423 diff.capLength2D(maxLookDistance);
10424 dest += diff;
10425 }
10426 else {
10427 avatar->looking = 0;
10428 }
10429 }
10430
10431 if (cameraLerpDelay==0)
10432 {
10433 //cameraLerpDelay = 0.15;
10434 cameraLerpDelay = vars->defaultCameraLerpDelay;
10435 }
10436 Vector oldCamPos = dsq->cameraPos;
10437 cameraInterp.stop();
10438 cameraInterp.interpolateTo(dest, cameraLerpDelay);
10439 dsq->cameraPos = getCameraPositionFor(cameraInterp);
10440 constrainCamera();
10441
10442 float dd = (dsq->cameraPos - oldCamPos).getLength2D();
10443 }
10444
10445 cameraInterp.update(dt);
10446 }
10447
10448 }
10449
setElementLayerVisible(int bgLayer,bool v)10450 void Game::setElementLayerVisible(int bgLayer, bool v)
10451 {
10452 core->getRenderObjectLayer(LR_ELEMENTS1+bgLayer)->visible = v;
10453 }
10454
isElementLayerVisible(int bgLayer)10455 bool Game::isElementLayerVisible(int bgLayer)
10456 {
10457 return core->getRenderObjectLayer(LR_ELEMENTS1+bgLayer)->visible;
10458 }
10459
10460 /*
10461 void Game::cameraPanToNode(Path *p, int speed)
10462 {
10463
10464 cameraFollow = &p->nodes[0].position;
10465 }
10466
10467 void Game::cameraRestore()
10468 {
10469 setCameraFollow(avatar);
10470 }
10471 */
10472
fireShot(const std::string & bankShot,Entity * firer,Entity * target,const Vector & pos,const Vector & aim,bool playSfx)10473 Shot *Game::fireShot(const std::string &bankShot, Entity *firer, Entity *target, const Vector &pos, const Vector &aim, bool playSfx)
10474 {
10475 Shot *s = 0;
10476 if (firer)
10477 {
10478 s = new Shot;
10479 s->firer = firer;
10480
10481 if (pos.isZero())
10482 s->position = firer->position;
10483 else
10484 s->position = pos;
10485
10486 if (target)
10487 s->setTarget(target);
10488
10489 Shot::loadBankShot(bankShot, s);
10490
10491 if (!aim.isZero())
10492 s->setAimVector(aim);
10493 else
10494 {
10495 if (target && firer)
10496 s->setAimVector(target->position - firer->position);
10497 else if (firer)
10498 s->setAimVector(firer->getNormal());
10499 else
10500 s->setAimVector(Vector(0,1));
10501 }
10502
10503 s->updatePosition();
10504 s->fire(playSfx);
10505
10506
10507 core->getTopStateData()->addRenderObject(s, LR_PROJECTILES);
10508 }
10509
10510 return s;
10511 }
10512
fireShot(Entity * firer,const std::string & particleEffect,Vector position,bool big,Vector dir,Entity * target,int homing,int velLenOverride,int targetPt)10513 Shot* Game::fireShot(Entity *firer, const std::string &particleEffect, Vector position, bool big, Vector dir, Entity *target, int homing, int velLenOverride, int targetPt)
10514 {
10515 //sound->playSfx("BasicShot", 255, 0, rand()%100 + 1000);
10516 /*
10517 DamageType dt;
10518 if (firer->getEntityType() == ET_ENEMY)
10519 dt = DT_ENEMY_ENERGYBLAST;
10520 else if (firer->getEntityType() == ET_AVATAR)
10521 dt = DT_AVATAR_ENERGYBLAST;
10522 else
10523 debugLog("UNDEFINED DAMAGE TYPE!");
10524 int velLen = 900;
10525 if (big)
10526 velLen += 200;
10527 if (velLenOverride != 0)
10528 velLen = velLenOverride;
10529 Shot *shot;
10530 if (big && target)
10531 shot = new Shot(dt, firer, position, target, "energyBlast", homing, velLen, 8, 0.1, 4, 2);
10532 else
10533 {
10534 if (homing > 0)
10535 shot = new Shot(dt, firer, position, target, "energyBlast", homing, velLen, 5, 0.1, 4, 1);
10536 else
10537 shot = new Shot(dt, firer, position, 0, "energyBlast", 0, velLen, 5, 0.1, 4, 1);
10538 }
10539 shot->setParticleEffect(particleEffect);
10540 if (big)
10541 shot->scale = Vector(1.5, 1.5);
10542 //shot->velocity = dsq->getGameCursorPosition() - position;
10543 if (dir.x == 0 && dir.y == 0 && target)
10544 {
10545 shot->velocity = target->position - firer->position;
10546 }
10547 else
10548 {
10549 shot->velocity = dir;
10550 }
10551 if (velLen != 0 && !shot->velocity.isZero())
10552 shot->velocity.setLength2D(velLen);
10553
10554 if (firer->getEntityType() == ET_AVATAR && homing && target)
10555 {
10556 //std::ostringstream os;
10557 //os << "targetvel(" << target->vel.x << ", " << target->vel.y << ")";
10558 //debugLog(os.str());
10559 if (!target->vel.isZero() && !target->vel.isNan())
10560 shot->velocity += target->vel;
10561 }
10562 shot->targetPt = targetPt;
10563 //shot->velocity += firer->vel;
10564
10565 core->getTopStateData()->addRenderObject(shot, LR_PROJECTILES);
10566 return shot;
10567 */
10568 debugLog("Old version of Game::fireShot is obsolete");
10569 return 0;
10570 }
10571
warpCameraTo(RenderObject * r)10572 void Game::warpCameraTo(RenderObject *r)
10573 {
10574 warpCameraTo(r->position);
10575 }
10576
warpCameraTo(Vector position)10577 void Game::warpCameraTo(Vector position)
10578 {
10579 cameraInterp.stop();
10580 cameraInterp = position;
10581 dsq->cameraPos = getCameraPositionFor(position);
10582 }
10583
snapCam()10584 void Game::snapCam()
10585 {
10586 if (cameraFollow)
10587 warpCameraTo(*cameraFollow);
10588 }
10589
getElementTemplateForLetter(int i)10590 ElementTemplate Game::getElementTemplateForLetter(int i)
10591 {
10592 float cell = 64.0f/512.0f;
10593 //for (int i = 0; i < 27; i++)
10594 ElementTemplate t;
10595 t.idx = 1024+i;
10596 t.gfx = "Aquarian";
10597 int x = i,y=0;
10598 while (x >= 6)
10599 {
10600 x -= 6;
10601 y++;
10602 }
10603
10604 t.tu1 = x*cell;
10605 t.tv1 = y*cell;
10606 t.tu2 = t.tu1 + cell;
10607 t.tv2 = t.tv1 + cell;
10608
10609 t.tv2 = 1 - t.tv2;
10610 t.tv1 = 1 - t.tv1;
10611 std::swap(t.tv1,t.tv2);
10612
10613 t.w = 512*cell;
10614 t.h = 512*cell;
10615 //elementTemplates.push_back(t);
10616 return t;
10617 }
10618
loadElementTemplates(std::string pack)10619 void Game::loadElementTemplates(std::string pack)
10620 {
10621
10622 stringToLower(pack);
10623 /*
10624 std::string fn = ("data/"+pack+".xml");
10625 if (!exists(fn))
10626 {
10627 loadElementTemplatesDAT(pack);
10628 return;
10629 }
10630 loadElementTemplatesXML(pack);
10631 */
10632
10633 elementTemplates.clear();
10634
10635 // HACK: need to uncache things! causes memory leak currently
10636 bool doPrecache=false;
10637 std::string fn;
10638
10639 if (dsq->mod.isActive())
10640 fn = dsq->mod.getPath() + "tilesets/" + pack + ".txt";
10641 else
10642 fn = "data/tilesets/" + pack + ".txt";
10643
10644
10645 if (lastTileset == fn)
10646 {
10647 doPrecache=false;
10648 }
10649
10650 lastTileset = fn;
10651 if (!exists(fn))
10652 {
10653 errorLog ("Could not open element template pack [" + fn + "]");
10654 return;
10655 }
10656
10657 if (doPrecache)
10658 {
10659 tileCache.clean();
10660 }
10661
10662 InStream in(fn.c_str());
10663 std::string line;
10664 while (std::getline(in, line))
10665 {
10666 int idx=-1, w=-1, h=-1;
10667 std::string gfx;
10668 std::istringstream is(line);
10669 is >> idx >> gfx >> w >> h;
10670 ElementTemplate t;
10671 t.idx = idx;
10672 t.gfx = gfx;
10673 if (w==0) w=-1;
10674 if (h==0) h=-1;
10675 t.w = w;
10676 t.h = h;
10677 elementTemplates.push_back(t);
10678 if (doPrecache)
10679 tileCache.precacheTex(gfx);
10680 }
10681 in.close();
10682
10683 for (int i = 0; i < elementTemplates.size(); i++)
10684 {
10685 for (int j = i; j < elementTemplates.size(); j++)
10686 {
10687 if (elementTemplates[i].idx > elementTemplates[j].idx)
10688 {
10689 std::swap(elementTemplates[i], elementTemplates[j]);
10690 }
10691 }
10692 }
10693 for (int i = 0; i < 27; i++)
10694 {
10695 elementTemplates.push_back(getElementTemplateForLetter(i));
10696 }
10697 }
10698
clearGrid(int v)10699 void Game::clearGrid(int v)
10700 {
10701 // ensure that grid is really a byte-array
10702 compile_assert(sizeof(grid) == MAX_GRID * MAX_GRID);
10703
10704 memset(grid, v, sizeof(grid));
10705 }
10706
resetFromTitle()10707 void Game::resetFromTitle()
10708 {
10709 overrideMusic = "";
10710 }
10711
setGrid(ElementTemplate * et,Vector position,float rot360)10712 void Game::setGrid(ElementTemplate *et, Vector position, float rot360)
10713 {
10714 for (int i = 0; i < et->grid.size(); i++)
10715 {
10716 TileVector t(position);
10717 /*
10718 std::ostringstream os;
10719 os << "opos(" << position.x << ", " << position.y << ") centre(" << t.x << ", " << t.y << ")";
10720 debugLog(os.str());
10721 */
10722 int x = et->grid[i].x;
10723 int y = et->grid[i].y;
10724 if (rot360 >= 0 && rot360 < 90)
10725 {
10726 }
10727 else if (rot360 >= 90 && rot360 < 180)
10728 {
10729 int swap = y;
10730 y = x;
10731 x = swap;
10732 x = -x;
10733 }
10734 else if (rot360 >= 180 && rot360 < 270)
10735 {
10736 x = -x;
10737 y = -y;
10738 }
10739 else if (rot360 >= 270 && rot360 < 360)
10740 {
10741 int swap = y;
10742 y = x;
10743 x = swap;
10744 y = -y;
10745 }
10746 TileVector s(t.x+x, t.y+y);
10747 //Vector v = Vector(position.x+et->grid[i].x*TILE_SIZE, position.y+et->grid[i].y*TILE_SIZE);
10748 setGrid(s, OT_INVISIBLE);
10749 }
10750 }
10751
removeState()10752 void Game::removeState()
10753 {
10754 const float fadeTime = 0.25;
10755
10756 dsq->toggleVersionLabel(false);
10757
10758 dsq->subtitlePlayer.hide(fadeTime);
10759
10760 dropIngrNames.clear();
10761
10762 debugLog("Entering Game::removeState");
10763 shuttingDownGameState = true;
10764 debugLog("avatar->endOfGameState()");
10765 if (avatar)
10766 {
10767 avatar->endOfGameState();
10768 }
10769
10770 #ifdef AQUARIA_BUILD_SCENEEDITOR
10771 debugLog("toggle sceneEditor");
10772 if (sceneEditor.isOn())
10773 sceneEditor.toggle(false);
10774 #endif
10775
10776 debugLog("gameSpeed");
10777 dsq->gameSpeed.interpolateTo(1, 0);
10778
10779 debugLog("bgSfxLoop");
10780
10781 dsq->loops.stopAll();
10782
10783 debugLog("toggleCursor");
10784
10785 dsq->toggleCursor(0, fadeTime);
10786
10787 if (!isInGameMenu())
10788 avatar->disableInput();
10789
10790 debugLog("control hint");
10791
10792 controlHint_ignoreClear = false;
10793 clearControlHint();
10794 dsq->overlay->color = 0;
10795
10796 //dsq->overlay->alpha = 0;
10797 dsq->overlay->alpha.interpolateTo(1, fadeTime);
10798 dsq->main(fadeTime);
10799
10800 /*
10801 // to block on voice overs
10802 while (dsq->isStreamingVoice())
10803 {
10804 dsq->main(FRAME_TIME);
10805 }
10806 */
10807 // AFTER TRANSITION:
10808
10809 dsq->rumble(0,0,0);
10810
10811 dsq->sound->clearFadingSfx();
10812
10813
10814 ingredients.clear();
10815
10816 core->particlesPaused = false;
10817
10818 elementUpdateList.clear();
10819 elementInteractionList.clear();
10820
10821 dsq->setCursor(CURSOR_NORMAL);
10822 dsq->darkLayer.toggle(0);
10823 dsq->shakeCamera(0,0);
10824 if (core->afterEffectManager)
10825 core->afterEffectManager->clear();
10826
10827 dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = true;
10828
10829 //core->sound->fadeOut(1);
10830 if (saveFile)
10831 {
10832 delete saveFile;
10833 saveFile = 0;
10834 }
10835 /*
10836 if (core->getEnqueuedJumpState() != "Game")
10837 {
10838 this->overrideMusic = "";
10839 }
10840 */
10841 dsq->continuity.zoom = core->globalScale;
10842
10843 dsq->game->toggleOverrideZoom(false);
10844 dsq->game->avatar->myZoom.stop();
10845 dsq->globalScale.stop();
10846
10847 dsq->game->avatar->myZoom = Vector(1,1);
10848 dsq->globalScale = Vector(1,1);
10849 core->globalScaleChanged();
10850
10851 for (int i = 0; i < getNumPaths(); i++)
10852 {
10853 Path *p = getPath(i);
10854 p->destroy();
10855 delete p;
10856 }
10857 clearPaths();
10858
10859 StateObject::removeState();
10860 dsq->clearElements();
10861 dsq->clearEntities();
10862 avatar = 0;
10863 //items.clear();
10864 #ifdef AQUARIA_BUILD_SCENEEDITOR
10865 sceneEditor.shutdown();
10866 #endif
10867
10868 cameraFollow = 0;
10869 core->cameraPos = Vector(0,0);
10870 sceneColor.stop();
10871
10872 controlHint_mouseLeft = controlHint_mouseRight = controlHint_mouseMiddle = controlHint_mouseBody = controlHint_bg = controlHint_image = 0;
10873 controlHint_text = 0;
10874
10875 miniMapRender = 0;
10876 gridRender = 0;
10877 gridRender2 = 0;
10878 gridRender3 = 0;
10879 edgeRender = 0;
10880 gridRenderEnt = 0;
10881 gridRenderUser1 = 0;
10882 gridRenderUser2 = 0;
10883 worldMapRender = 0;
10884 //core->sound->stopStreamingOgg();
10885
10886 // optimize:: clear layers
10887 /*
10888 int c = 0;
10889 for (DSQ::RenderObjectLayers::iterator i = core->renderObjectLayers.begin(); i != core->renderObjectLayers.end(); i++)
10890 {
10891 DSQ::RenderObjects *r = &(*i);
10892 //if (c <= LR_HUD)
10893 if (c<=LR_PARTICLES)
10894 r->clear();
10895 c++;
10896 }
10897 */
10898
10899 clearObsRows();
10900
10901
10902 debugLog("killAllShots");
10903 Shot::killAllShots();
10904 Shot::clearShotGarbage(); // make sure there are no pointers left (would lead to a crash on shutdown otherwise)
10905 debugLog("killAllBeams");
10906 Beam::killAllBeams();
10907 debugLog("killAllWebs");
10908 Web::killAllWebs();
10909 debugLog("killAllSpores");
10910 Spore::killAllSpores();
10911
10912 debugLog("clear Local Sounds");
10913 core->sound->clearLocalSounds();
10914
10915 active = false;
10916
10917
10918 dsq->routeShoulder = true;
10919
10920
10921
10922 debugLog("Game::removeState Done");
10923 //core->sound->stopAllSounds();
10924 }
10925
isActive()10926 bool Game::isActive()
10927 {
10928 return active;
10929 }
10930
isBoxIn(Vector pos1,Vector sz1,Vector pos2,Vector sz2)10931 bool isBoxIn(Vector pos1, Vector sz1, Vector pos2, Vector sz2)
10932 {
10933 if ((pos1.x - sz1.x > pos2.x-sz2.x) && (pos1.x - sz1.x < pos2.x+sz2.x))
10934 {
10935 if ((pos1.y - sz1.y > pos2.y-sz2.y) && (pos1.y - sz1.y < pos2.y+sz2.y))
10936 return true;
10937 else if ((pos1.y + sz1.y > pos2.y-sz2.y) && (pos1.y + sz1.y < pos2.y+sz2.y))
10938 return true;
10939 }
10940 else if ((pos1.x + sz1.x > pos2.x-sz2.x) && (pos1.x + sz1.x < pos2.x+sz2.x))
10941 {
10942 if ((pos1.y - sz1.y > pos2.y-sz2.y) && (pos1.y - sz1.y < pos2.y+sz2.y))
10943 return true;
10944 else if ((pos1.y + sz1.y > pos2.y-sz2.y) && (pos1.y + sz1.y < pos2.y+sz2.y))
10945 return true;
10946 }
10947 return false;
10948 }
10949
getClosestPointOnTriangle(Vector a,Vector b,Vector c,Vector p)10950 Vector Game::getClosestPointOnTriangle(Vector a, Vector b, Vector c, Vector p)
10951 {
10952 Vector Rab = getClosestPointOnLine(a, b, p);
10953 Vector Rbc = getClosestPointOnLine(b, c, p);
10954 Vector Rca = getClosestPointOnLine(c, a, p);
10955 int RabDist = Rab.getSquaredLength2D();
10956 int RbcDist = Rab.getSquaredLength2D();
10957 int RcaDist = Rca.getSquaredLength2D();
10958 if (RabDist < RbcDist && RabDist < RcaDist)
10959 {
10960 return Rab;
10961 }
10962 if (RbcDist < RabDist && RbcDist < RcaDist)
10963 return Rbc;
10964 return Rca;
10965 }
10966
getClosestPointOnLine(Vector a,Vector b,Vector p)10967 Vector Game::getClosestPointOnLine(Vector a, Vector b, Vector p)
10968 {
10969 // Determine t (the length of the vector from a to p)
10970 Vector c = p - a;
10971 Vector V = b-a;
10972 V.normalize2D();
10973 float d = (a-b).getLength2D();
10974 float t = V.dot(c);
10975
10976 // Check to see if t is beyond the extents of the line segment
10977
10978 if (t < 0) return a;
10979 if (t > d) return b;
10980
10981 // Return the point between a and b
10982
10983 //set length of V to t;
10984 V.setLength2D(t);
10985 return a + V;
10986 }
10987
collideCircleWithGrid(const Vector & position,float r)10988 bool Game::collideCircleWithGrid(const Vector& position, float r)
10989 {
10990 Vector tile = position;
10991 TileVector t(tile);
10992 tile.x = t.x;
10993 tile.y = t.y;
10994
10995 float hsz = TILE_SIZE/2;
10996 int xrange=1,yrange=1;
10997 xrange = (r/TILE_SIZE)+1;
10998 yrange = (r/TILE_SIZE)+1;
10999
11000 for (int x = tile.x-xrange; x <= tile.x+xrange; x++)
11001 {
11002 for (int y = tile.y-yrange; y <= tile.y+yrange; y++)
11003 {
11004 int v = this->getGrid(TileVector(x, y));
11005 if (v != 0)
11006 {
11007 //if (tile.x == x && tile.y == y) return true;
11008 TileVector t(x, y);
11009 lastCollidePosition = t.worldVector();
11010 //if (tile.x == x && tile.y == y) return true;
11011 float rx = (x*TILE_SIZE)+TILE_SIZE/2;
11012 float ry = (y*TILE_SIZE)+TILE_SIZE/2;
11013
11014 float rSqr;
11015 lastCollideTileType = (ObsType)v;
11016
11017 rSqr = sqr(position.x - (rx+hsz)) + sqr(position.y - (ry+hsz));
11018 if (rSqr < sqr(r)) return true;
11019
11020 rSqr = sqr(position.x - (rx-hsz)) + sqr(position.y - (ry+hsz));
11021 if (rSqr < sqr(r)) return true;
11022
11023 rSqr = sqr(position.x - (rx-hsz)) + sqr(position.y - (ry-hsz));
11024 if (rSqr < sqr(r)) return true;
11025
11026 rSqr = sqr(position.x - (rx+hsz)) + sqr(position.y - (ry-hsz));
11027 if (rSqr < sqr(r)) return true;
11028
11029
11030 if (position.x > rx-hsz && position.x < rx+hsz)
11031 {
11032 if (fabsf(ry - position.y) < r+hsz)
11033 {
11034 return true;
11035 }
11036 }
11037
11038
11039 if (position.y > ry-hsz && position.y < ry+hsz)
11040 {
11041 if (fabsf(rx - position.x) < r+hsz)
11042 {
11043 return true;
11044 }
11045 }
11046 }
11047 }
11048 }
11049 lastCollideTileType = OT_EMPTY;
11050 return false;
11051 }
11052
learnedRecipe(Recipe * r,bool effects)11053 void Game::learnedRecipe(Recipe *r, bool effects)
11054 {
11055 if (nocasecmp(dsq->getTopStateData()->name,"Game")==0 && !applyingState)
11056 {
11057 std::ostringstream os;
11058 os << dsq->continuity.stringBank.get(23) << " " << r->resultDisplayName << " " << dsq->continuity.stringBank.get(24);
11059 IngredientData *data = dsq->continuity.getIngredientDataByName(r->result);
11060 if (data)
11061 {
11062 if (effects)
11063 {
11064 dsq->game->setControlHint(os.str(), 0, 0, 0, 3, std::string("gfx/ingredients/") + data->gfx);
11065 }
11066 }
11067
11068 /*
11069 errorLog(os.str());
11070 */
11071 }
11072 }
11073
setIgnoreAction(AquariaActions ac,bool ignore)11074 void Game::setIgnoreAction(AquariaActions ac, bool ignore)
11075 {
11076 if (ignore)
11077 ignoredActions.insert(ac);
11078 else
11079 ignoredActions.erase(ac);
11080 }
11081
isIgnoreAction(AquariaActions ac) const11082 bool Game::isIgnoreAction(AquariaActions ac) const
11083 {
11084 return ignoredActions.find(ac) != ignoredActions.end();
11085 }
11086