voxelands/src/enchantment.cpp

237 lines
4.5 KiB
C++

/************************************************************************
* enchantment.cpp
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2015 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
************************************************************************/
#include "enchantment.h"
#include <stdio.h>
#include "content_craftitem.h"
/*
1 - Aeterna ---
1 - +
1 - +
1 - Velox ---
1 - +
1 - +
1 -
1 -
1 -
1 -
1 -
1 -
1 - Amplius --------
1 - Indomitus --- +
1 - + +
1 - Ignis +
*/
EnchantmentInfo enchantments[ENCHANTMENT_MAX+1];
static int enchantment_isinit = 0;
static void enchantment_init()
{
EnchantmentInfo *f;
uint8_t i;
for (i=0; i<=ENCHANTMENT_MAX; i++) {
f = &enchantments[i];
f->type = ENCHANTMENT_NONE;
f->level = 0;
f->mask = 0;
f->overlay = "";
f->name = (char*)"";
f->gem = CONTENT_IGNORE;
}
i = ENCHANTMENT_FLAME;
f = &enchantments[i];
f->type = i;
f->mask = (1<<(i-1));
f->overlay = "flame";
f->name = (char*)"Ignis";
f->gem = CONTENT_CRAFTITEM_SUNSTONE;
i = ENCHANTMENT_DONTBREAK;
f = &enchantments[i];
f->type = i;
f->mask = (1<<(i-1));
f->overlay = "dontbreak";
f->name = (char*)"Indomitus";
f->gem = CONTENT_CRAFTITEM_SAPPHIRE;
i = ENCHANTMENT_MORE;
f = &enchantments[i];
f->type = i;
f->mask = (1<<(i-1));
f->overlay = "more";
f->name = (char*)"Amplius";
f->gem = CONTENT_CRAFTITEM_TURQUOISE;
i = ENCHANTMENT_FAST;
f = &enchantments[i];
f->type = i;
f->mask = (1<<(i-1));
f->overlay = "fast";
f->name = (char*)"Velox";
f->gem = CONTENT_CRAFTITEM_AMETHYST;
i = ENCHANTMENT_LONGLASTING;
f = &enchantments[i];
f->type = i;
f->mask = (1<<(i-1));
f->overlay = "longlast";
f->name = (char*)"Aeterna";
f->gem = CONTENT_CRAFTITEM_RUBY;
enchantment_isinit = 1;
}
/* read and remove one enchantment from data,
* call repeatedly to iterate over all enchantments */
bool enchantment_get(uint16_t *data, EnchantmentInfo *info)
{
uint16_t d;
int8_t i;
uint8_t l = 0;
if (!data)
return false;
d = *data;
if (d == ENCHANTMENT_NONE)
return false;
if (!enchantment_isinit)
enchantment_init();
for (i=15; i>-1; i--) {
if ((d&(1<<i)) == 0)
continue;
if (enchantments[i+1].mask == (1<<i))
break;
}
if (i < 0) {
*data = 0;
return false;
}
if (i > 2) {
d = (d>>(i-2));
d &= 0x0003;
l = 1+d;
}else{
l = 1;
}
if (info) {
*info = enchantments[i+1];
info->level = l;
}
for (d=0; d<3 && i>-1; d++,i--) {
(*data) &= ~(1<<i);
}
return true;
}
/* check if data contains an enchantment */
bool enchantment_have(uint16_t data, uint16_t enchantment)
{
if (!enchantment_isinit)
enchantment_init();
EnchantmentInfo info;
while (enchantment_get(&data,&info)) {
if (info.type == enchantment)
return true;
}
return false;
}
bool enchantment_set(uint16_t *data, uint16_t enchantment)
{
uint16_t d;
EnchantmentInfo info;
if (!data)
return false;
if (!enchantment_isinit)
enchantment_init();
if (!enchantment_get(&enchantment,&info))
return false;
d = *data;
if ((d&info.mask) == 0) {
*data |= info.mask;
return true;
}
if (info.type > 2) {
u8 l = 0;
d = (d>>(info.type-3));
d &= 0x0003;
l = d;
*data &= ~(3<<(info.type-3));
if (l < 3) {
l++;
*data |= (l<<(info.type-3));
}
}
return true;
}
bool enchantment_enchant(uint16_t *data, content_t item)
{
int i;
if (!enchantment_isinit)
enchantment_init();
for (i=0; i<=ENCHANTMENT_MAX; i++) {
if (enchantments[i].gem == item) {
*data = enchantments[i].mask;
return true;
}
}
return false;
}
uint16_t enchantment_create(uint16_t enchantment, uint8_t level)
{
uint16_t d;
if (!enchantment_isinit)
enchantment_init();
if (!level || enchantment == ENCHANTMENT_NONE || enchantment > ENCHANTMENT_MAX || enchantments[enchantment].type != enchantment)
return 0;
d = enchantments[enchantment].mask;
if (enchantment > 2) {
if (level > 3)
level = 3;
d |= (level<<(enchantment-3));
}
return d;
}