1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 /*!****************************************************************************
11 * \file    skill_editor.h
12 * \author  Daniel Steuernol, steu@allacrost.org
13 * \brief   Header file for editor's skill editor dialog
14 *****************************************************************************/
15 
16 #include "skill_editor.h"
17 
18 using namespace std;
19 
20 using namespace hoa_utils;
21 
22 using namespace hoa_script;
23 using namespace hoa_global;
24 using namespace hoa_editor;
25 
26 
SkillEditor(QWidget * parent,const QString & name)27 SkillEditor::SkillEditor(QWidget *parent, const QString &name)
28 : QWidget(parent, static_cast<const char *>(name))
29 {
30 	setCaption("Skill Editor");
31 
32 	_current_skill_index[GLOBAL_SKILL_ATTACK] = -1;
33 	_current_skill_index[GLOBAL_SKILL_DEFEND] = -1;
34 	_current_skill_index[GLOBAL_SKILL_SUPPORT] = -1;
35 
36 
37 	_LoadSkills();
38 
39 	// initialize tabs
40 	_tab_skill_groups = new QTabWidget();
41 	_tab_skill_groups->setTabPosition(QTabWidget::North);
42 	connect(_tab_skill_groups, SIGNAL(currentChanged(int)), this, SLOT(_ChangeCurrentTab(int)));
43 
44 	// set up the layout boxes
45 	_hbox = new QHBoxLayout();
46 	_hbox->addWidget(_tab_skill_groups);
47 
48 	// add layout to form
49 	setLayout(_hbox);
50 
51 	_CreateTab(GLOBAL_SKILL_ATTACK, _attack_skills, "attack");
52 	_CreateTab(GLOBAL_SKILL_DEFEND, _defense_skills, "defense");
53 	_CreateTab(GLOBAL_SKILL_SUPPORT, _support_skills, "support");
54 
55 	_current_tab = GLOBAL_SKILL_ATTACK;
56 } // SkillEditor
57 
~SkillEditor()58 SkillEditor::~SkillEditor()
59 {
60 	for (uint32 i = 0; i < _attack_skills.size(); ++i)
61 		delete _attack_skills[i];
62 	for (uint32 i = 0; i < _defense_skills.size(); ++i)
63 		delete _defense_skills[i];
64 	for (uint32 i = 0; i < _support_skills.size(); ++i)
65 		delete _support_skills[i];
66 
67 	_CleanupTab(GLOBAL_SKILL_ATTACK);
68 	_CleanupTab(GLOBAL_SKILL_DEFEND);
69 	_CleanupTab(GLOBAL_SKILL_SUPPORT);
70 
71 	delete _hbox;
72 	delete _tab_skill_groups;
73 } // ~SkillEditor
74 
_ChangeCurrentTab(int index)75 void SkillEditor::_ChangeCurrentTab(int index)
76 {
77 	if (index == 0)
78 		_current_tab = GLOBAL_SKILL_ATTACK;
79 	else if (index == 1)
80 		_current_tab = GLOBAL_SKILL_DEFEND;
81 	else if (index == 2)
82 		_current_tab = GLOBAL_SKILL_SUPPORT;
83 } // _ChangeCurrentTab()
84 
_LeftButtonClicked()85 void SkillEditor::_LeftButtonClicked()
86 {
87 	_current_skill_index[_current_tab]--;
88 	if (_current_skill_index[_current_tab] < 0)
89 		_current_skill_index[_current_tab] = _GetCurrentSkillList().size() - 1;
90 
91 	_ReloadTab();
92 } // _LeftButtonClicked()
93 
_RightButtonClicked()94 void SkillEditor::_RightButtonClicked()
95 {
96 	_current_skill_index[_current_tab]++;
97 	if (_current_skill_index[_current_tab] >= static_cast<int32>(_GetCurrentSkillList().size()))
98 		_current_skill_index[_current_tab] = 0;
99 
100 	_ReloadTab();
101 } // _RightButtonClicked()
102 
_LoadSkills()103 void SkillEditor::_LoadSkills()
104 {
105 	string path = string("dat/skills/");
106 	ReadScriptDescriptor script;
107 	script.OpenFile(path + "defense.lua", true);
108 	script.CloseFile();
109 	script.OpenFile(path + "support.lua", true);
110 	script.CloseFile();
111 	vector<GlobalSkill *> skills;
112 	if (script.OpenFile(path + "attack.lua", true) != false)
113 		_LoadSkills(script, skills, GLOBAL_SKILL_ATTACK);
114 	// Now clean up the skills script (due to the way we're storing the scripts in lua, they're all actually in one big table in lua
115 	// regardless of the file split on disk
116 	vector<GlobalSkill *>::iterator i = skills.begin();
117 	for (; i != skills.end(); ++i)
118 	{
119 		if ((*i)->GetType() == GLOBAL_SKILL_ATTACK)
120 			_attack_skills.push_back(*i);
121 		else if ((*i)->GetType() == GLOBAL_SKILL_DEFEND)
122 			_defense_skills.push_back(*i);
123 		else if ((*i)->GetType() == GLOBAL_SKILL_SUPPORT)
124 			_support_skills.push_back(*i);
125 	}
126 	if (_attack_skills.size() > 0)
127 		_current_skill_index[GLOBAL_SKILL_ATTACK] = 0;
128 	if (_defense_skills.size() > 0)
129 		_current_skill_index[GLOBAL_SKILL_DEFEND] = 0;
130 	if (_support_skills.size() > 0)
131 		_current_skill_index[GLOBAL_SKILL_SUPPORT] = 0;
132 
133 } // _LoadSkills()
134 
_LoadSkills(ReadScriptDescriptor & script,vector<GlobalSkill * > & skills,GLOBAL_SKILL type)135 void SkillEditor::_LoadSkills(ReadScriptDescriptor &script, vector<GlobalSkill *> &skills, GLOBAL_SKILL type)
136 {
137 	script.OpenTable("skills");
138 	vector<uint32> keys;
139 	script.ReadTableKeys(keys);
140 	for (uint32 i = 0; i < keys.size(); ++i)
141 		skills.push_back(new GlobalSkill(keys[i]));
142 	script.CloseAllTables();
143 	script.CloseFile();
144 
145 } // _LoadSkills(ReadScriptDescriptor, vector<GlobalSkill *>)
146 
_CreateTab(GLOBAL_SKILL type,vector<GlobalSkill * > skills,QString tab_name)147 void SkillEditor::_CreateTab(GLOBAL_SKILL type, vector<GlobalSkill *>skills, QString tab_name)
148 {
149 	_gl_layouts[type] = new QGridLayout();
150 	// add the labels for the different parts of the skill
151 	_lbl_skill_names[type] = new QLabel();
152 	_lbl_skill_names[type]->setText("Skill Name:");
153 	_gl_layouts[type]->addWidget(_lbl_skill_names[type], 0, 0);
154 
155 	_lbl_description[type] = new QLabel();
156 	_lbl_description[type]->setText("Description:");
157 	_gl_layouts[type]->addWidget(_lbl_description[type], 1, 0);
158 
159 	_lbl_sp_required[type] = new QLabel();
160 	_lbl_sp_required[type]->setText("SP Required:");
161 	_gl_layouts[type]->addWidget(_lbl_sp_required[type], 2, 0);
162 
163 	_lbl_warmup_time[type] = new QLabel();
164 	_lbl_warmup_time[type]->setText("Warmup Time:");
165 	_gl_layouts[type]->addWidget(_lbl_warmup_time[type], 2, 2);
166 
167 	_lbl_cooldown_time[type] = new QLabel();
168 	_lbl_cooldown_time[type]->setText("Cooldown Time:");
169 	_gl_layouts[type]->addWidget(_lbl_cooldown_time[type], 3, 0);
170 
171 	_lbl_target_type[type] = new QLabel();
172 	_lbl_target_type[type]->setText("Target Type:");
173 	_gl_layouts[type]->addWidget(_lbl_target_type[type], 4, 0);
174 
175 	// add the line edits for the skill
176 	_le_skill_names[type] = new QLineEdit();
177 	_le_description[type] = new QLineEdit();
178 	_le_sp_required[type] = new QLineEdit();
179 	_le_warmup_time[type] = new QLineEdit();
180 	_le_cooldown_time[type] = new QLineEdit();
181 	_cb_target_type[type] = new QComboBox();
182 
183 	if (_current_skill_index[type] != -1)
184 	{
185 		GlobalSkill *skill = skills[_current_skill_index[type]];
186 		// this skill is enabled so set the text
187 		string text = MakeStandardString(skill->GetName());
188 		// get the char array from the standard string, because otherwise the QString ends up with
189 		// some gibberish text at the beginning of it
190 		_le_skill_names[type]->setText(QString(text.c_str()));
191 
192 		text = MakeStandardString(skill->GetDescription());
193 		_le_description[type]->setText(QString(text.c_str()));
194 
195 		text = NumberToString<uint32>(skill->GetSPRequired());
196 		_le_sp_required[type]->setText(QString(text.c_str()));
197 
198 		text = NumberToString<uint32>(skill->GetWarmupTime());
199 		_le_warmup_time[type]->setText(QString(text.c_str()));
200 
201 		text = NumberToString<uint32>(skill->GetCooldownTime());
202 		_le_cooldown_time[type]->setText(QString(text.c_str()));
203 
204 		_cb_target_type[type]->insertItem("Attack Point");
205 		_cb_target_type[type]->insertItem("Actor");
206 		_cb_target_type[type]->insertItem("Party");
207 		_cb_target_type[type]->setCurrentIndex(static_cast<int32>(skill->GetTargetType()));
208 	}
209 	else
210 	{
211 		// disable the line edits (no skills for this group)
212 		_le_skill_names[type]->setDisabled(true);
213 		_le_description[type]->setDisabled(true);
214 		_le_sp_required[type]->setDisabled(true);
215 		_le_warmup_time[type]->setDisabled(true);
216 		_le_cooldown_time[type]->setDisabled(true);
217 		_cb_target_type[type]->setDisabled(true);
218 		_rb_target_ally_false[type]->setDisabled(true);
219 		_rb_target_ally_true[type]->setDisabled(true);
220 	}
221 
222 	// add above widgets to grid layout
223 	_gl_layouts[type]->addWidget(_le_skill_names[type], 0, 1, 1, 3);
224 	_gl_layouts[type]->addWidget(_le_description[type], 1, 1, 1, 3);
225 	_gl_layouts[type]->addWidget(_le_sp_required[type], 2, 1);
226 	_gl_layouts[type]->addWidget(_le_warmup_time[type], 2, 3);
227 	_gl_layouts[type]->addWidget(_le_cooldown_time[type], 3, 1);
228 	_gl_layouts[type]->addWidget(_cb_target_type[type], 4, 1);
229 	_hbox_target_ally[type] = new QHBoxLayout();
230 	_hbox_target_ally[type]->addWidget(_rb_target_ally_true[type]);
231 	_hbox_target_ally[type]->addWidget(_rb_target_ally_false[type]);
232 	_target_ally_spacers[type] = new QSpacerItem(10, 5, QSizePolicy::Expanding);
233 	_hbox_target_ally[type]->addItem(_target_ally_spacers[type]);
234 	_gl_layouts[type]->addLayout(_hbox_target_ally[type], 3, 3);
235 
236 	// create the vertical layout for the tab
237 	_tab_vboxes[type] = new QVBoxLayout();
238 	_tab_vboxes[type]->addLayout(_gl_layouts[type]);
239 
240 	// add a spacer to the vbox to push up the grid layout
241 	_tab_spacers[type] = new QSpacerItem(10,5, QSizePolicy::Minimum, QSizePolicy::Expanding);
242 	_tab_vboxes[type]->addItem(_tab_spacers[type]);
243 
244 	// create the horizontal layout underneath the grid in the tab
245 	_tab_bottom_hboxes[type] = new QHBoxLayout();
246 
247 	_CreateTabBottomButtons(type);
248 
249 	_tab_vboxes[type]->addLayout(_tab_bottom_hboxes[type]);
250 
251 	_tab_pages[type] = new QWidget();
252 	_tab_pages[type]->setLayout(_tab_vboxes[type]);
253 	_tab_skill_groups->addTab(_tab_pages[type], tab_name);
254 } // _CreateTab(GLOBAL_SKILL)
255 
_CreateTabBottomButtons(GLOBAL_SKILL type)256 void SkillEditor::_CreateTabBottomButtons(GLOBAL_SKILL type)
257 {
258 	// add all the buttons
259 	_new_buttons[type] = new QPushButton();
260 	_new_buttons[type]->setText("Create New Skill");
261 	_new_buttons[type]->setDisabled(true);
262 	_new_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
263 	_tab_bottom_hboxes[type]->addWidget(_new_buttons[type]);
264 
265 	_save_buttons[type] = new QPushButton();
266 	_save_buttons[type]->setText("Save Changes");
267 	_save_buttons[type]->setDisabled(true);
268 	_save_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
269 	_tab_bottom_hboxes[type]->addWidget(_save_buttons[type]);
270 
271 	// this spacer pushes the nav buttons to the right, and the other 2 buttons to the left
272 	_button_spacers[type] = new QSpacerItem(30, 10, QSizePolicy::Expanding);
273 	_tab_bottom_hboxes[type]->addItem(_button_spacers[type]);
274 
275 	_left_buttons[type] = new QPushButton();
276 	_left_buttons[type]->setIcon(QIcon("img/misc/editor-tools/arrow-left.png"));
277 	_left_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
278 	connect(_left_buttons[type], SIGNAL(clicked()), this, SLOT(_LeftButtonClicked()));
279 	_tab_bottom_hboxes[type]->addWidget(_left_buttons[type]);
280 
281 	_right_buttons[type] = new QPushButton();
282 	_right_buttons[type]->setIcon(QIcon("img/misc/editor-tools/arrow-right.png"));
283 	_right_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
284 	connect(_right_buttons[type], SIGNAL(clicked()), this, SLOT(_RightButtonClicked()));
285 	_tab_bottom_hboxes[type]->addWidget(_right_buttons[type]);
286 }
287 
_CleanupTab(GLOBAL_SKILL type)288 void SkillEditor::_CleanupTab(GLOBAL_SKILL type)
289 {
290 	delete _tab_vboxes[type];
291 	delete _tab_bottom_hboxes[type];
292 	delete _gl_layouts[type];
293 	delete _tab_pages[type];
294 	delete _left_buttons[type];
295 	delete _right_buttons[type];
296 	delete _save_buttons[type];
297 	delete _button_spacers[type];
298 	delete _tab_spacers[type];
299 	delete _lbl_skill_names[type];
300 	delete _lbl_description[type];
301 	delete _lbl_sp_required[type];
302 	delete _lbl_warmup_time[type];
303 	delete _lbl_cooldown_time[type];
304 	delete _lbl_target_type[type];
305 	delete _le_skill_names[type];
306 	delete _le_description[type];
307 	delete _le_sp_required[type];
308 	delete _le_warmup_time[type];
309 	delete _le_cooldown_time[type];
310 	delete _cb_target_type[type];
311 	delete _bg_target_ally[type];
312 	delete _rb_target_ally_true[type];
313 	delete _rb_target_ally_false[type];
314 	delete _hbox_target_ally[type];
315 	delete _target_ally_spacers[type];
316 } // _CleanupTab(GLOBAL_SKILL)
317 
_GetCurrentSkillList()318 vector<GlobalSkill *> &SkillEditor::_GetCurrentSkillList()
319 {
320 	if (_current_tab == GLOBAL_SKILL_ATTACK)
321 		return _attack_skills;
322 	else if (_current_tab == GLOBAL_SKILL_DEFEND)
323 		return _defense_skills;
324 	return _support_skills;
325 } // _GetCurrentSkillList
326 
_ReloadTab()327 void SkillEditor::_ReloadTab()
328 {
329 
330 	if (_GetCurrentSkillList().empty()) {
331 		return;
332 	}
333 
334 	GlobalSkill *skill = _GetCurrentSkillList()[_current_skill_index[_current_tab]];
335 
336 	string text = MakeStandardString(skill->GetName());
337 	_le_skill_names[_current_tab]->setText(QString(text.c_str()));
338 
339 	text = MakeStandardString(skill->GetDescription());
340 	_le_description[_current_tab]->setText(QString(text.c_str()));
341 
342 	text = NumberToString<uint32>(skill->GetSPRequired());
343 	_le_sp_required[_current_tab]->setText(QString(text.c_str()));
344 
345 	text = NumberToString<uint32>(skill->GetWarmupTime());
346 	_le_warmup_time[_current_tab]->setText(QString(text.c_str()));
347 
348 	text = NumberToString<uint32>(skill->GetCooldownTime());
349 	_le_cooldown_time[_current_tab]->setText(QString(text.c_str()));
350 
351 	_cb_target_type[_current_tab]->setCurrentIndex(static_cast<int32>(skill->GetTargetType()));
352 
353 	// TODO: as more controls are added to the tab, reload them here.
354 }
355 
356