]> git.localhorst.tv Git - alttp.git/blob - resources/js/components/common/ZeldaIcon.js
svg dungeon tracker
[alttp.git] / resources / js / components / common / ZeldaIcon.js
1 import PropTypes from 'prop-types';
2 import React from 'react';
3 import { useTranslation } from 'react-i18next';
4
5 import Icon from './Icon';
6
7 const ITEM_MAP = [
8     'aga',
9     'armos',
10     'arrghus',
11     'big-key',
12     'blind',
13     'blue-boomerang',
14     'blue-mail',
15     'blue-pendant',
16     'blue-potion',
17     'bombos',
18     'bomb',
19     'book',
20     'boots',
21     'bottle-bee',
22     'bottle-good-bee',
23     'bottle',
24     'bowless-silvers',
25     'bow',
26     'bugnet',
27     'bunny-head',
28     'byrna',
29     'cape',
30     'chest',
31     'compass',
32     'crystal',
33     'crystal-switch-blue',
34     'crystal-switch',
35     'crystal-switch-red',
36     'duck',
37     'ether',
38     'fairy',
39     'fighter-shield',
40     'fighter-sword',
41     'fire-rod',
42     'fire-shield',
43     'flippers',
44     'flute',
45     'ganon',
46     'glove',
47     'gold-sword',
48     'green-mail',
49     'green-pendant',
50     'green-potion',
51     'gt',
52     'half-magic',
53     'hammer',
54     'heart-0',
55     'heart-1',
56     'heart-2',
57     'heart-3',
58     'heart-container',
59     'heart-piece',
60     'helma',
61     'hookshot',
62     'ice-rod',
63     'kholdstare',
64     'lamp',
65     'lanmolas',
66     'link-head',
67     'map',
68     'master-sword',
69     'mirror',
70     'mirror-shield',
71     'mitts',
72     'moldorm',
73     'moonpearl',
74     'mothula',
75     'mushroom',
76     'open-chest',
77     'powder',
78     'quake',
79     'quarter-magic',
80     'red-bomb',
81     'red-boomerang',
82     'red-crystal',
83     'red-mail',
84     'red-pendant',
85     'red-potion',
86     'shovel',
87     'silvers',
88     'small-key',
89     'somaria',
90     'sword-1',
91     'sword-2',
92     'sword-3',
93     'sword-4',
94     'tempered-sword',
95     'triforce-piece',
96     'triforce',
97     'trinexx',
98     'vitreous',
99 ];
100
101 const ITEM_MAP_WIDTH = 8;
102
103 const ITEM_MAP_HEIGHT = Math.ceil(ITEM_MAP.length / ITEM_MAP_WIDTH);
104
105 const ITEM_MAP_URL = '/items-v2.png';
106
107 const isOnItemMap = name => ITEM_MAP.includes(name);
108
109 const getItemMapX = name => ITEM_MAP.indexOf(name) % ITEM_MAP_WIDTH;
110
111 const getItemMapY = name => Math.floor(ITEM_MAP.indexOf(name) / ITEM_MAP_WIDTH);
112
113 const getItemMapStyle = name => {
114         const x = getItemMapX(name);
115         const y = getItemMapY(name);
116         return {
117                 backgroundImage: `url(${ITEM_MAP_URL})`,
118                 backgroundPosition: `-${x * 100}% -${y * 100}%`,
119                 backgroundSize: `${ITEM_MAP_WIDTH * 100}% ${ITEM_MAP_HEIGHT * 100}%`,
120         };
121 };
122
123 const getIconURL = name => {
124         switch (name) {
125                 case 'dungeon-ct':
126                 case 'dungeon-dp':
127                 case 'dungeon-ep':
128                 case 'dungeon-gt':
129                 case 'dungeon-hc':
130                 case 'dungeon-ip':
131                 case 'dungeon-mm':
132                 case 'dungeon-pd':
133                 case 'dungeon-sp':
134                 case 'dungeon-sw':
135                 case 'dungeon-th':
136                 case 'dungeon-tr':
137                 case 'dungeon-tt':
138                         return `/dungeon/${name.substr(8)}.png`;
139                 default:
140                         return '';
141         }
142 };
143
144 const isHalfWidth = name => [
145         'blue-boomerang',
146         'fire-rod',
147         'ice-rod',
148         'hookshot',
149         'red-boomerang',
150 ].includes(name);
151
152 const ZeldaIcon = ({ name, svg, title }) => {
153         const { t } = useTranslation();
154
155         const invert = name.startsWith('not-');
156         const strippedName = invert ? name.substr(4) : name;
157         const src = getIconURL(strippedName);
158         const alt = t(`icon.zelda.${name}`);
159         const realTitle = title !== '' ? title || alt : null;
160
161         if (svg) {
162                 const clipX = getItemMapX(strippedName);
163                 const clipY = getItemMapY(strippedName);
164                 const cropX = isHalfWidth(strippedName) ? 0.25 : 0.02;
165                 const cropY = 0.02;
166                 const cropW = 1 - (2 * cropX);
167                 const cropH = 1 - (2 * cropY);
168                 return <image
169                         href={isOnItemMap(strippedName) ? ITEM_MAP_URL : src}
170                         width={ITEM_MAP_WIDTH}
171                         height={ITEM_MAP_HEIGHT}
172                         x="0"
173                         y="0"
174                         transform={`translate(-${clipX + 0.5} -${clipY + 0.5})`}
175                         clipPath={`xywh(${clipX + cropX} ${clipY + cropY} ${cropW} ${cropH})`}
176                 >
177                         {realTitle ?
178                                 <title>{realTitle}</title>
179                         : null}
180                 </image>;
181         }
182
183         return <span className="zelda-icon">
184                 {isOnItemMap(strippedName) ?
185                         <span
186                                 className="item-map-icon"
187                                 style={getItemMapStyle(strippedName)}
188                                 title={realTitle}
189                         />
190                 : null}
191                 {src ?
192                         <img
193                                 alt={alt}
194                                 src={src}
195                                 title={realTitle}
196                         />
197                 : null}
198                 {invert ?
199                         <span className="strike">
200                                 <Icon.SLASH title="" />
201                         </span>
202                 : null}
203         </span>;
204 };
205
206 ZeldaIcon.propTypes = {
207         name: PropTypes.string.isRequired,
208         svg: PropTypes.bool,
209         title: PropTypes.string,
210 };
211
212 export default ZeldaIcon;