/* * glyphwindow.cpp - Author: Anders Reggestad * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include // CS INCLUDES #include #include #include // COMMON INCLUDES #include "net/message.h" #include "net/msghandler.h" #include "net/cmdhandler.h" #include "util/strutil.h" #include "util/log.h" // CLIENT INCLUDES #include "pscelclient.h" #include "../globals.h" #include "gui/psmainwidget.h" // PAWS INCLUDES #include "paws/pawstextbox.h" #include "paws/pawsprefmanager.h" #include "pawsglyphwindow.h" #include "paws/pawsmanager.h" #include "paws/pawsbutton.h" #include "paws/pawsobjectview.h" #include "paws/pawstexturemanager.h" #include "paws/pawslistbox.h" #define PURIFY_BUTTON 1000 #define SAVE_BUTTON 1001 #define CAST_BUTTON 1002 #define RESEARCH_BUTTON 1003 ////////////////////////////////////////////////////////////////////// // // pawsGlyphWindow // ////////////////////////////////////////////////////////////////////// pawsGlyphWindow::pawsGlyphWindow() { msgHandler = NULL; for (int i = 0; i < GLYPH_ASSEMBLER_SLOTS; i++) assembler[i] = NULL; } pawsGlyphWindow::~pawsGlyphWindow() { } void pawsGlyphWindow::Show() { pawsWidget::Show(); // Ask the server to send us the glyphs psRequestGlyphsMessage outGoingMessage; msgHandler->SendMessage( outGoingMessage.msg ); } void pawsGlyphWindow::Hide() { pawsGlyphSlot * floatingSlot = dynamic_cast (PawsManager::GetSingleton().GetDragDropWidget()); if ( floatingSlot!=NULL ) PawsManager::GetSingleton().SetDragDropWidget(NULL); pawsWidget::Hide(); } bool pawsGlyphWindow::PostSetup() { int i; msgHandler = psengine->GetMsgHandler(); if ( !msgHandler ) return false; // Subscribe our message types that we are interested in. if ( !msgHandler->Subscribe( this, MSGTYPE_GLPYH_REQUEST ) ) return false; if ( !msgHandler->Subscribe( this, MSGTYPE_GLYPH_ASSEMBLE ) ) return false; description = dynamic_cast (FindWidget("SpellDescription")); if ( !description ) return false; spellName = dynamic_cast (FindWidget("SpellName")); if ( !spellName ) return false; ways.SetLength(GLYPH_WAYS); ways[0] = dynamic_cast (FindWidget("crystal")); if ( !ways[0] ) return false; ways[1] = dynamic_cast (FindWidget("blue")); if ( !ways[1] ) return false; ways[2] = dynamic_cast (FindWidget("azure")); if ( !ways[2] ) return false; ways[3] = dynamic_cast (FindWidget("brown")); if ( !ways[3] ) return false; ways[4] = dynamic_cast (FindWidget("red")); if ( !ways[4] ) return false; ways[5] = dynamic_cast (FindWidget("dark")); if ( !ways[5] ) return false; for (int wayNum=0; wayNum < GLYPH_WAYS; wayNum++) for (i=0; i < 3; i++) NewGlyphSlotRow(wayNum); for (i=0; i < GLYPH_ASSEMBLER_SLOTS; i++) { csString slotName; slotName = "assembler"; slotName += i; assembler[i] = dynamic_cast (FindWidget(slotName)); if (assembler[i] == NULL) return false; assembler[i]->SetStatID( 0 ); assembler[i]->SetDrag(false); } return true; } void pawsGlyphWindow::HandleMessage ( MsgEntry* me ) { switch( me->GetType() ) { case MSGTYPE_GLPYH_REQUEST: { HandleGlyphList(me); break; } case MSGTYPE_GLYPH_ASSEMBLE: { HandleAssemble( me ); break; } } } void pawsGlyphWindow::HandleGlyphList( MsgEntry* me ) { psRequestGlyphsMessage msg( me ); csArray < pawsGlyphSlot* > usedSlots; pawsGlyphSlot * floatingSlot = dynamic_cast (PawsManager::GetSingleton().GetDragDropWidget()); for ( size_t x = 0; x < msg.glyphs.Length(); x++ ) { if (msg.glyphs[x].way>=GLYPH_WAYS) continue; if (floatingSlot!=NULL && floatingSlot->GetStatID()==msg.glyphs[x].statID && floatingSlot->GetPurifyStatus()==msg.glyphs[x].purifiedStatus) { if (msg.glyphs[x].count > 0) msg.glyphs[x].count--; else PawsManager::GetSingleton().SetDragDropWidget(NULL); } if (msg.glyphs[x].purifiedStatus==2) { int assemblerCount = CountTypeInAssembler(msg.glyphs[x].statID); if ((size_t)assemblerCount > msg.glyphs[x].count) { RemoveTypeFromAssembler(assemblerCount - msg.glyphs[x].count); assemblerCount = msg.glyphs[x].count; } msg.glyphs[x].count -= assemblerCount; } pawsGlyphSlot * itemSlot = FindAppropriateSlotForGlyph(msg.glyphs, msg.glyphs[x]); CS_ASSERT(itemSlot); itemSlot->PlaceItem(msg.glyphs[x].image, msg.glyphs[x].count); itemSlot->SetStatID(msg.glyphs[x].statID); itemSlot->SetPurifyStatus(msg.glyphs[x].purifiedStatus); itemSlot->SetToolTip( msg.glyphs[x].name ); usedSlots.Push(itemSlot); } ClearUnusedGlyphs(usedSlots); for (int slotNum=0; slotNum < GLYPH_ASSEMBLER_SLOTS; slotNum++) if (GetGlyphTypeSlot(assembler[slotNum]->GetStatID(), assembler[slotNum]->GetPurifyStatus()) == NULL) assembler[slotNum]->Clear(); if (floatingSlot!=NULL && GetGlyphTypeSlot(floatingSlot->GetStatID(), floatingSlot->GetPurifyStatus()) == NULL) PawsManager::GetSingleton().SetDragDropWidget(NULL); } int pawsGlyphWindow::CountTypeInAssembler(int statID) { int count=0; for (int slotNum=0; slotNum < GLYPH_ASSEMBLER_SLOTS; slotNum++) if (assembler[slotNum]->GetStatID()==statID) count++; return count; } pawsGlyphSlot * pawsGlyphWindow::FindFreeAssemblerSlot() { for (int slotNum=0; slotNum < GLYPH_ASSEMBLER_SLOTS; slotNum++) if (assembler[slotNum]->GetStatID() == 0) return assembler[slotNum]; return NULL; } void pawsGlyphWindow::RemoveTypeFromAssembler(int statID) { for (int slotNum=0; slotNum < GLYPH_ASSEMBLER_SLOTS; slotNum++) if (assembler[slotNum]->GetStatID() == statID) { assembler[slotNum]->Clear(); assembler[slotNum]->SetDefaultToolTip(); return; } } void pawsGlyphWindow::NewGlyphSlotRow(int wayNum) { if (wayNum<0 || wayNum>=GLYPH_WAYS) return; ways[wayNum]->NewRow(); } bool HasReceivedGlyph(const csArray & recvGlyphs, int statID, int purifyStatus) { size_t glyphNum; for (glyphNum=0; glyphNum < recvGlyphs.Length(); glyphNum++) if (recvGlyphs[glyphNum].statID==statID && recvGlyphs[glyphNum].purifiedStatus==purifyStatus) return true; return false; } pawsGlyphSlot * pawsGlyphWindow::FindAppropriateSlotForGlyph(const csArray & recvGlyphs, const psRequestGlyphsMessage::NetworkGlyph& glyph) { pawsGlyphSlot * slot; slot = GetGlyphTypeSlot(glyph.statID, glyph.purifiedStatus); if (slot != NULL) return slot; if (glyph.purifiedStatus>0 && !HasReceivedGlyph(recvGlyphs, glyph.statID, glyph.purifiedStatus-1)) { slot = GetGlyphTypeSlot(glyph.statID, glyph.purifiedStatus-1); if (slot != NULL) return slot; } return FindFreeSlot(glyph.way); } void pawsGlyphWindow::HandleAssemble( MsgEntry* me ) { psGlyphAssembleMessage mesg; mesg.FromServer( me ); description->Clear(); spellName->SetText(mesg.name); description->AddMessage( mesg.description ); description->ResetScroll(); } void pawsGlyphWindow::ClearSpell( void ) { description->Clear(); spellName->SetText( "" ); description->ResetScroll(); } void pawsGlyphWindow::ClearUnusedGlyphs(const csArray & usedSlots) { int wayNum, rowNum, colNum; pawsListBox * way; pawsListBoxRow * row; pawsGlyphSlot * slot; for (wayNum=0; wayNum < GLYPH_WAYS; wayNum++) { way = ways[wayNum]; for (rowNum=0; rowNum < way->GetRowCount(); rowNum++) { row = way->GetRow(rowNum); for (colNum=0; colNum < way->GetTotalColumns(); colNum++) { slot = dynamic_cast (row->GetColumn(colNum)); if (slot!=NULL && usedSlots.Find(slot)==-1) { slot->Clear(); } } } } } pawsGlyphSlot * pawsGlyphWindow::FindFreeSlot(int wayNum) { int rowNum, colNum; pawsListBox * way; pawsListBoxRow * row; pawsGlyphSlot * slot; way = ways[wayNum]; for (rowNum=0; rowNum < way->GetRowCount(); rowNum++) { row = way->GetRow(rowNum); for (colNum=0; colNum < way->GetTotalColumns(); colNum++) { slot = dynamic_cast (row->GetColumn(colNum)); if (slot!=NULL && slot->IsEmpty()) return slot; } } // no free slot available ? then create new row NewGlyphSlotRow(wayNum); return dynamic_cast (way->GetRow(way->GetRowCount()-1)->GetColumn(0)); } pawsGlyphSlot * pawsGlyphWindow::GetGlyphTypeSlot(int statID, int purifyStatus) { int wayNum, rowNum, colNum; pawsListBox * way; pawsListBoxRow * row; pawsGlyphSlot * slot; for (wayNum=0; wayNum < GLYPH_WAYS; wayNum++) { way = ways[wayNum]; for (rowNum=0; rowNum < way->GetRowCount(); rowNum++) { row = way->GetRow(rowNum); for (colNum=0; colNum < way->GetTotalColumns(); colNum++) { slot = dynamic_cast (row->GetColumn(colNum)); if (slot!=NULL && slot->GetStatID()==statID && slot->GetPurifyStatus()==purifyStatus) return slot; } } } return NULL; } bool pawsGlyphWindow::OnButtonPressed( int mouseButton, int keyModifier, pawsWidget* widget ) { pawsGlyphSlot * floatingSlot = dynamic_cast (PawsManager::GetSingleton().GetDragDropWidget()); pawsGlyphSlot * clickedSlot = dynamic_cast (widget); csString slotName = widget->GetName(); // Check to see if this was the purify button. if ( widget->GetID() == PURIFY_BUTTON ) { if (floatingSlot!=NULL && floatingSlot->GetPurifyStatus()==0) { psPurifyGlyphMessage mesg( floatingSlot->GetStatID() ); msgHandler->SendMessage( mesg.msg ); PawsManager::GetSingleton().SetDragDropWidget(NULL); } return true; } // Check to see if this was the save button. if ( widget->GetID() == SAVE_BUTTON ) { if (!spellName->GetText()) return true; if (strcmp(spellName->GetText(),"")!=0) { csString name(spellName->GetText()); psSaveSpellMessage mesg( name ); msgHandler->SendMessage( mesg.msg ); } return true; } // Check to see if this was the cast button. if ( widget->GetID() == CAST_BUTTON ) { if (!spellName->GetText()) return true; if (strcmp(spellName->GetText(),"")!=0) { csString name(spellName->GetText()); psSpellCastMessage mesg( name, psengine->GetKFactor() ); msgHandler->SendMessage( mesg.msg ); } return true; } // Check to see if this was the research button. if ( widget->GetID() == RESEARCH_BUTTON ) { SendAssembler(); return true; } if (clickedSlot == NULL) return true; // user clicked on one of the assembler slots if (slotName.Slice(0, 9) == "assembler") { if (floatingSlot == NULL) { if (clickedSlot->StackCount() > 0) { CreateFloatingSlot(clickedSlot); clickedSlot->Clear(); } } else if (floatingSlot->GetPurifyStatus() == 2) { pawsGlyphSlot * slot = FindFreeAssemblerSlot(); if (slot != NULL) { slot->PlaceItem(floatingSlot->ImageName(), 1); slot->SetStatID(floatingSlot->GetStatID()); slot->SetPurifyStatus(floatingSlot->GetPurifyStatus()); PawsManager::GetSingleton().SetDragDropWidget(NULL); ClearSpell(); } } else { psSystemMessage error(0,MSG_ERROR,PawsManager::GetSingleton().Translate("Not a purified glyph")); error.FireEvent(); } } // user clicked on one of the glyph slots else { if (floatingSlot == NULL) { if (clickedSlot->StackCount() > 0) { CreateFloatingSlot(clickedSlot); clickedSlot->StackCount(clickedSlot->StackCount() - 1); } } else { pawsGlyphSlot * targetSlot = GetGlyphTypeSlot(floatingSlot->GetStatID(), floatingSlot->GetPurifyStatus()); if (targetSlot != NULL) { targetSlot->StackCount(targetSlot->StackCount() + 1); PawsManager::GetSingleton().SetDragDropWidget(NULL); ClearSpell(); } } } return true; } void pawsGlyphWindow::CreateFloatingSlot(pawsGlyphSlot * sourceSlot) { pawsGlyphSlot * floatingSlot = new pawsGlyphSlot(); floatingSlot->PlaceItem( sourceSlot->ImageName(), 1 ); floatingSlot->SetStatID(sourceSlot->GetStatID()); floatingSlot->SetPurifyStatus(sourceSlot->GetPurifyStatus()); floatingSlot->SetBackgroundAlpha(0); PawsManager::GetSingleton().SetDragDropWidget( floatingSlot ); } void pawsGlyphWindow::SendAssembler() { psGlyphAssembleMessage mesg( assembler[0]->GetStatID(), assembler[1]->GetStatID(), assembler[2]->GetStatID(), assembler[3]->GetStatID() ); msgHandler->SendMessage( mesg.msg ); }